summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/canvas
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /testing/web-platform/tests/html/canvas
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/canvas')
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.pngbin207 -> 0 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.pngbin112 -> 0 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.png (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.png)bin207 -> 207 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.pngbin205 -> 0 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.pngbin207 -> 0 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.pngbin112 -> 0 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.pngbin205 -> 0 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.png (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.png)bin205 -> 205 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.png (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.png)bin117 -> 117 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.png (renamed from testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.png)bin207 -> 207 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html85
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html101
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur-expected.html85
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.html106
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.beginLayer-options.html7
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html7
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.exceptions-are-no-op.html7
-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.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation.html81
-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.blending.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation.html87
-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.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation.html81
-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.composite.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation.html87
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation.html81
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation.html87
-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.html39
-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.html39
-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.html38
-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.html42
-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.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html81
-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.blending.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation.html87
-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.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html81
-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.composite.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation.html87
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html81
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation.html87
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html81
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html87
-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-composite-op.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html81
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html83
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html87
-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.globalCompositeOperation-expected.html910
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.globalCompositeOperation.html861
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html7
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-restore.html7
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html7
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.endLayer.html7
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-beginLayer-restore.html7
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-endLayer.html7
-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.html40
-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.html87
-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/manual/filters/svg-filter-lh-rlh-expected.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-lh-rlh.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter.svg10
-rw-r--r--testing/web-platform/tests/html/canvas/element/text/WEB_FEATURES.yml4
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html30
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.worker.js25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html30
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.worker.js25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html30
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.worker.js25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html30
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.worker.js25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html121
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.w.html194
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur-expected.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.w.html199
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow-expected.html36
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.html42
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.w.html56
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.w.html52
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow-expected.html36
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.html42
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.w.html56
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.w.html52
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.w.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.w.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.w.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.w.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.w.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.w.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html42
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.w.html59
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html56
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html42
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.w.html59
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html56
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html41
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html59
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.html40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.w.html58
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.w.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.html40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.w.html58
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.w.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html98
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html102
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html104
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html108
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.html40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.w.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow-expected.html53
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.html43
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.w.html57
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform-expected.html72
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.w.html116
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html76
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html89
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.w.html120
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html78
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html91
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.w.html122
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html82
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html95
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.w.html126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.w.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.html40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.w.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation-expected.html910
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.html961
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.w.html1314
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.html11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.worker.js11
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.worker.js21
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.worker.js21
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.worker.js37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.html34
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.worker.js29
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.html36
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.worker.js31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.html34
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.worker.js29
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.html85
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.worker.js32
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.html34
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.worker.js29
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.worker.js84
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/text/WEB_FEATURES.yml4
-rw-r--r--testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py387
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/reftest_element.html2
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/reftest_element_grid.html56
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/reftest_grid.html30
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen.html2
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen_grid.html52
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/reftest_worker.html2
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/reftest_worker_grid.html62
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/testharness_element_grid.html52
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/testharness_offscreen_grid.html28
-rw-r--r--testing/web-platform/tests/html/canvas/tools/templates/testharness_worker_grid.js27
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml8
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml292
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml/element/meta.yaml14
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml/offscreen/meta.yaml14
447 files changed, 22814 insertions, 7651 deletions
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html
deleted file mode 100644
index 59d66c383c..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-1</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.fillStyle.parse.hsl-clamp-1</h1>
-<p class="desc"></p>
-
-<p class="notes">
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-1.png" class="output expected" id="expected" alt="">
-<ul id="d"></ul>
-<script>
-var t = async_test("");
-_addTest(function(canvas, ctx) {
-
- ctx.fillStyle = '#f00';
- ctx.fillStyle = 'hsl(120, 200%, 50%)';
- ctx.fillRect(0, 0, 100, 50);
- _assertPixel(canvas, 50,25, 0,255,0,255);
-
-});
-</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html
deleted file mode 100644
index 56f3a0a8b5..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-3</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.fillStyle.parse.hsl-clamp-3</h1>
-<p class="desc"></p>
-
-<p class="notes">
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-3.png" class="output expected" id="expected" alt="">
-<ul id="d"></ul>
-<script>
-var t = async_test("");
-_addTest(function(canvas, ctx) {
-
- ctx.fillStyle = '#f00';
- ctx.fillStyle = 'hsl(120, 100%, 200%)';
- ctx.fillRect(0, 0, 100, 50);
- _assertPixel(canvas, 50,25, 255,255,255,255);
-
-});
-</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.png
deleted file mode 100644
index bf48767a88..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.png
+++ /dev/null
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html
deleted file mode 100644
index af9d11e678..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-4</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.fillStyle.parse.hsl-clamp-4</h1>
-<p class="desc"></p>
-
-<p class="notes">
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-4.png" class="output expected" id="expected" alt="">
-<ul id="d"></ul>
-<script>
-var t = async_test("");
-_addTest(function(canvas, ctx) {
-
- ctx.fillStyle = '#f00';
- ctx.fillStyle = 'hsl(120, 100%, -200%)';
- ctx.fillRect(0, 0, 100, 50);
- _assertPixel(canvas, 50,25, 0,0,0,255);
-
-});
-</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.png
deleted file mode 100644
index d638d03386..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.png
+++ /dev/null
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html
index 1a1939e47a..65440c6228 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.html
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html
@@ -1,19 +1,19 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-2</title>
+<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-negative-saturation</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.fillStyle.parse.hsl-clamp-2</h1>
+<h1>2d.fillStyle.parse.hsl-clamp-negative-saturation</h1>
<p class="desc"></p>
<p class="notes">
<p class="output">Actual output:</p>
<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-2.png" class="output expected" id="expected" alt="">
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-negative-saturation.png" class="output expected" id="expected" alt="">
<ul id="d"></ul>
<script>
var t = async_test("");
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.png
index 88fd827985..88fd827985 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.png
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html
deleted file mode 100644
index 2acac26e1a..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-1</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.fillStyle.parse.hsla-clamp-1</h1>
-<p class="desc"></p>
-
-<p class="notes">
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-1.png" class="output expected" id="expected" alt="">
-<ul id="d"></ul>
-<script>
-var t = async_test("");
-_addTest(function(canvas, ctx) {
-
- ctx.fillStyle = '#f00';
- ctx.fillStyle = 'hsla(120, 200%, 50%, 1)';
- ctx.fillRect(0, 0, 100, 50);
- _assertPixel(canvas, 50,25, 0,255,0,255);
-
-});
-</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.png
deleted file mode 100644
index 2733836c99..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.png
+++ /dev/null
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html
deleted file mode 100644
index 4bc134aec5..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-3</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.fillStyle.parse.hsla-clamp-3</h1>
-<p class="desc"></p>
-
-<p class="notes">
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-3.png" class="output expected" id="expected" alt="">
-<ul id="d"></ul>
-<script>
-var t = async_test("");
-_addTest(function(canvas, ctx) {
-
- ctx.fillStyle = '#f00';
- ctx.fillStyle = 'hsla(120, 100%, 200%, 1)';
- ctx.fillRect(0, 0, 100, 50);
- _assertPixel(canvas, 50,25, 255,255,255,255);
-
-});
-</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.png
deleted file mode 100644
index bf48767a88..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.png
+++ /dev/null
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html
deleted file mode 100644
index f8b2382755..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-4</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.fillStyle.parse.hsla-clamp-4</h1>
-<p class="desc"></p>
-
-<p class="notes">
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-4.png" class="output expected" id="expected" alt="">
-<ul id="d"></ul>
-<script>
-var t = async_test("");
-_addTest(function(canvas, ctx) {
-
- ctx.fillStyle = '#f00';
- ctx.fillStyle = 'hsla(120, 100%, -200%, 1)';
- ctx.fillRect(0, 0, 100, 50);
- _assertPixel(canvas, 50,25, 0,0,0,255);
-
-});
-</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.png
deleted file mode 100644
index d638d03386..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.png
+++ /dev/null
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.png
deleted file mode 100644
index 2733836c99..0000000000
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.png
+++ /dev/null
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html
index 9c5e2258b9..e5dc98d4e3 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.html
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html
@@ -1,19 +1,19 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-5</title>
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-alpha-1</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.fillStyle.parse.hsla-clamp-5</h1>
+<h1>2d.fillStyle.parse.hsla-clamp-alpha-1</h1>
<p class="desc"></p>
<p class="notes">
<p class="output">Actual output:</p>
<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-5.png" class="output expected" id="expected" alt="">
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-alpha-1.png" class="output expected" id="expected" alt="">
<ul id="d"></ul>
<script>
var t = async_test("");
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.png
index 2733836c99..2733836c99 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.png
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html
index 153515eedd..26139a562e 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.html
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html
@@ -1,19 +1,19 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-6</title>
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-alpha-2</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.fillStyle.parse.hsla-clamp-6</h1>
+<h1>2d.fillStyle.parse.hsla-clamp-alpha-2</h1>
<p class="desc"></p>
<p class="notes">
<p class="output">Actual output:</p>
<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-6.png" class="output expected" id="expected" alt="">
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-alpha-2.png" class="output expected" id="expected" alt="">
<ul id="d"></ul>
<script>
var t = async_test("");
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.png
index eeedd0ff05..eeedd0ff05 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.png
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html
index 0f32fb5474..2d9b9d3bdf 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.html
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html
@@ -1,19 +1,19 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-2</title>
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-negative-saturation</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.fillStyle.parse.hsla-clamp-2</h1>
+<h1>2d.fillStyle.parse.hsla-clamp-negative-saturation</h1>
<p class="desc"></p>
<p class="notes">
<p class="output">Actual output:</p>
<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-2.png" class="output expected" id="expected" alt="">
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-negative-saturation.png" class="output expected" id="expected" alt="">
<ul id="d"></ul>
<script>
var t = async_test("");
diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.png b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.png
index 88fd827985..88fd827985 100644
--- a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.png
+++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
deleted file mode 100644
index dac31c97f1..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
deleted file mode 100644
index f4c8c1033a..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
deleted file mode 100644
index 88d0cb2de2..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 1" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
deleted file mode 100644
index b3efcb8c3e..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 1],
- });
- ctx.fillRect(25, 25, 50, 50);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
deleted file mode 100644
index 744983d4ae..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="1 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
deleted file mode 100644
index d5cc6e0058..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [1, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html
new file mode 100644
index 0000000000..c1ca0ab46f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative</title>
+<h1 style="font-size: 20px;">2d.filter.canvasFilterObject.gaussianBlur.tentative</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur0" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur0)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur1" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur1)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur2" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur2)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur3" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur3)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>y-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur4" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur4)" />
+ </svg>
+ </div>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
new file mode 100644
index 0000000000..498418c292
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative</title>
+<h1 style="font-size: 20px;">2d.filter.canvasFilterObject.gaussianBlur.tentative</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <canvas id="canvas0" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+ </script>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <canvas id="canvas1" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+ </script>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <canvas id="canvas2" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas2");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+ </script>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <canvas id="canvas3" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas3");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+ </script>
+</span>
+
+<span>
+ <div>y-only</div>
+ <canvas id="canvas4" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas4");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
deleted file mode 100644
index e611113e42..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 0" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
deleted file mode 100644
index 4e8576fe74..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 0],
- });
- ctx.fillRect(25, 25, 50, 50);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
deleted file mode 100644
index c6d915cb07..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="0 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
deleted file mode 100644
index ec0a2353cf..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [0, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur-expected.html
new file mode 100644
index 0000000000..f24e9d0dba
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur-expected.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur</title>
+<h1 style="font-size: 20px;">2d.filter.layers.gaussianBlur</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur0" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur0)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur1" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur1)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur2" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur2)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur3" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur3)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>y-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur4" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur4)" />
+ </svg>
+ </div>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.html
new file mode 100644
index 0000000000..19db679076
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur</title>
+<h1 style="font-size: 20px;">2d.filter.layers.gaussianBlur</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <canvas id="canvas0" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <canvas id="canvas1" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <canvas id="canvas2" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas2");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <canvas id="canvas3" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas3");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>y-only</div>
+ <canvas id="canvas4" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas4");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
deleted file mode 100644
index 4f93754862..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
-<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html
deleted file mode 100644
index a2cc098896..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.isotropic-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
-<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
deleted file mode 100644
index 255270c192..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 1" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html
deleted file mode 100644
index 0090e0e71e..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-x-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 1],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
deleted file mode 100644
index 76a46b1533..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="1 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html
deleted file mode 100644
index 5c481cbe25..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-y-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [1, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
deleted file mode 100644
index 26741f9847..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
-<h1>2d.filter.layers.gaussianBlur.x-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 0" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html
deleted file mode 100644
index f7940eb921..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.x-only-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
-<h1>2d.filter.layers.gaussianBlur.x-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 0],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
deleted file mode 100644
index d00eec6b57..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
-<h1>2d.filter.layers.gaussianBlur.y-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="0 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html
deleted file mode 100644
index 59421a1ff3..0000000000
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.y-only-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
-<h1>2d.filter.layers.gaussianBlur.y-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</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 = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [0, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- 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
index 658d7e0991..573d300055 100644
--- 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
@@ -16,8 +16,9 @@
<ul id="d"></ul>
<script>
-var t = async_test("Checks beginLayer works for different option parameter values");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
ctx.beginLayer(); ctx.endLayer();
ctx.beginLayer(null); ctx.endLayer();
@@ -45,6 +46,6 @@ _addTest(function(canvas, ctx) {
ctx.beginLayer({filter: true}); ctx.endLayer();
ctx.beginLayer({filter: false}); ctx.endLayer();
-});
+}, "Checks beginLayer works for different option parameter values");
</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html
index 7a69c59527..d669b3c522 100644
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html
@@ -16,8 +16,9 @@
<ul id="d"></ul>
<script>
-var t = async_test("Tests getTransform inside layers.");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
ctx.translate(10, 20);
ctx.beginLayer();
@@ -26,6 +27,6 @@ _addTest(function(canvas, ctx) {
assert_array_equals([m.a, m.b, m.c, m.d, m.e, m.f], [2, 0, 0, 3, 10, 20]);
ctx.endLayer();
-});
+}, "Tests getTransform inside layers.");
</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
index 7ab2080fca..facffd74e9 100644
--- 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
@@ -16,8 +16,9 @@
<ul id="d"></ul>
<script>
-var t = async_test("Checks that the context state is left unchanged if beginLayer throws.");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
// Get `beginLayer` to throw while parsing the filter.
assert_throws_js(TypeError,
@@ -26,6 +27,6 @@ _addTest(function(canvas, ctx) {
// `beginLayer` shouldn't have opened the layer, so `endLayer` should throw.
assert_throws_dom("InvalidStateError", () => ctx.endLayer());
-});
+}, "Checks that the context state is left unchanged if beginLayer throws.");
</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
deleted file mode 100644
index 0666e3098a..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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
deleted file mode 100644
index 8a45027588..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!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
deleted file mode 100644
index 8e15a2b936..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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
deleted file mode 100644
index f7b633b35f..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!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
deleted file mode 100644
index c8c6d433bc..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!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
deleted file mode 100644
index 951049e638..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!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
deleted file mode 100644
index 1ac6a2cbfe..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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
deleted file mode 100644
index 0ae93871f5..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!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
deleted file mode 100644
index 92b8a0d7a7..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!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
deleted file mode 100644
index 829796acbf..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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
deleted file mode 100644
index 6f764c5001..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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
deleted file mode 100644
index a325302b3b..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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
deleted file mode 100644
index 33fdf46a28..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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
deleted file mode 100644
index 7d4d9ae4b5..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..c56f13f2fd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.no-transform.html
new file mode 100644
index 0000000000..91decadfe2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..e5f8ba0db4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation.html
new file mode 100644
index 0000000000..d6b28315f2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index 6f969074f9..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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
deleted file mode 100644
index 51926d76d8..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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.blending.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..debbd430c4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.no-transform.html
new file mode 100644
index 0000000000..e0b8e45b51
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation-expected.html
new file mode 100644
index 0000000000..75a55e591b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation.html
new file mode 100644
index 0000000000..f3891369c9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index ed7669c4cf..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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
deleted file mode 100644
index 898d149924..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..cf87559582
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.no-transform.html
new file mode 100644
index 0000000000..195905e16b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..2f9bb208fb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation.html
new file mode 100644
index 0000000000..905fd7637b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index b687c27f47..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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
deleted file mode 100644
index c563a57b76..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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.composite.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..2b4436806a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.no-transform.html
new file mode 100644
index 0000000000..df008cf12e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation-expected.html
new file mode 100644
index 0000000000..da144975a5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation.html
new file mode 100644
index 0000000000..99e1d95443
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..489d432282
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform.html
new file mode 100644
index 0000000000..1720f20589
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..63913ffb05
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation.html
new file mode 100644
index 0000000000..87cd91bb12
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..021581f892
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform.html
new file mode 100644
index 0000000000..e8d01065c1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation-expected.html
new file mode 100644
index 0000000000..dd9a5c2a00
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation.html
new file mode 100644
index 0000000000..5c7fa379f1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.copy.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index f304700feb..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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
deleted file mode 100644
index 7c91ce4229..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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
deleted file mode 100644
index 98ea67e9e9..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-2453">
-<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
deleted file mode 100644
index 62942ffeae..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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
deleted file mode 100644
index ccadfb624b..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!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
deleted file mode 100644
index 8e0d98648e..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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
deleted file mode 100644
index 29041d4933..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-5204">
-<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
deleted file mode 100644
index a649972546..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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
deleted file mode 100644
index b2907f02aa..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!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
deleted file mode 100644
index 85718cffba..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6766">
-<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
deleted file mode 100644
index 169baee29b..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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
deleted file mode 100644
index aaeb167ccf..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6311">
-<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
deleted file mode 100644
index f81dcf72dc..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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
deleted file mode 100644
index 31628812c2..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..482ab25a85
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!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.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html
new file mode 100644
index 0000000000..188d5ea98b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..3af6b863ed
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!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.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html
new file mode 100644
index 0000000000..849a0c997e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index 91f3725f8e..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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
deleted file mode 100644
index e54cf06d0d..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!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.blending.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..d530ef9d19
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html
new file mode 100644
index 0000000000..34ded8fef5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html
new file mode 100644
index 0000000000..80705c36fd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation.html
new file mode 100644
index 0000000000..78407dd459
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index 97e85a1593..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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
deleted file mode 100644
index d7e365422f..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..2f513bff0a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!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.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html
new file mode 100644
index 0000000000..e3c36d3c0e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..242973300f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!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.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html
new file mode 100644
index 0000000000..466513864e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index 4716bb2760..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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
deleted file mode 100644
index e5c7698634..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!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.composite.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..c8926e5e15
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html
new file mode 100644
index 0000000000..bc7cfd314e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html
new file mode 100644
index 0000000000..e70fe3e92d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation.html
new file mode 100644
index 0000000000..f304e9c8e8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..21aa241aca
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html
new file mode 100644
index 0000000000..ac5c7303a8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!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.copy.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..b2b46ee039
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html
new file mode 100644
index 0000000000..3158a2fff3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!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.copy.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..d11326d5d6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html
new file mode 100644
index 0000000000..839ab13add
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!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.copy.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html
new file mode 100644
index 0000000000..3ac098c344
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation.html
new file mode 100644
index 0000000000..7c090165f5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.copy.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!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.copy.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..a445ae2c4a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!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-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html
new file mode 100644
index 0000000000..d2b2d806c4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!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-composite-op.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..610c601b1c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!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-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html
new file mode 100644
index 0000000000..afc4ebbd40
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!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-composite-op.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..6bd4501584
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!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-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html
new file mode 100644
index 0000000000..93caac12fc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!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-composite-op.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html
new file mode 100644
index 0000000000..b60a5526d9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!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-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html
new file mode 100644
index 0000000000..6849a2f40d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!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-composite-op.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index e56fe0b360..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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
deleted file mode 100644
index 68f4d5004a..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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
deleted file mode 100644
index 13ba2dd4cd..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!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
deleted file mode 100644
index 9efcd9d4f7..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!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-composite-op.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..d1a799707f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html
new file mode 100644
index 0000000000..f0fd2d19e3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html
@@ -0,0 +1,77 @@
+<!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-composite-op.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..cc91a67faf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html
new file mode 100644
index 0000000000..7ab850023e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html
@@ -0,0 +1,81 @@
+<!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-composite-op.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..02b239116c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html
new file mode 100644
index 0000000000..9da1936c5d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html
@@ -0,0 +1,83 @@
+<!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-composite-op.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html
new file mode 100644
index 0000000000..06f6a2dff3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html
new file mode 100644
index 0000000000..00ace7c54d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html
@@ -0,0 +1,87 @@
+<!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-composite-op.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
deleted file mode 100644
index b91a2ae8b5..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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
deleted file mode 100644
index d561be2341..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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
deleted file mode 100644
index 835e9d420a..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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
deleted file mode 100644
index 209316164c..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.globalCompositeOperation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.globalCompositeOperation-expected.html
new file mode 100644
index 0000000000..02a8915c0b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.globalCompositeOperation-expected.html
@@ -0,0 +1,910 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.globalCompositeOperation</title>
+<h1 style="font-size: 20px;">2d.layer.globalCompositeOperation</h1>
+<p class="desc">Checks that layers work with all globalCompositeOperation values.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(7, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>source-over</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>source-in</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>source-atop</div>
+ <canvas id="canvas2" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas2");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-over</div>
+ <canvas id="canvas3" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas3");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-in</div>
+ <canvas id="canvas4" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas4");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-out</div>
+ <canvas id="canvas5" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas5");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-atop</div>
+ <canvas id="canvas6" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas6");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>lighter</div>
+ <canvas id="canvas7" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas7");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighter';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>copy</div>
+ <canvas id="canvas8" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas8");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>xor</div>
+ <canvas id="canvas9" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas9");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>multiply</div>
+ <canvas id="canvas10" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas10");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>screen</div>
+ <canvas id="canvas11" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas11");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'screen';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>overlay</div>
+ <canvas id="canvas12" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas12");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'overlay';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>darken</div>
+ <canvas id="canvas13" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas13");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'darken';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>lighten</div>
+ <canvas id="canvas14" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas14");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighten';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color-dodge</div>
+ <canvas id="canvas15" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas15");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-dodge';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color-burn</div>
+ <canvas id="canvas16" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas16");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-burn';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>hard-light</div>
+ <canvas id="canvas17" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas17");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hard-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>soft-light</div>
+ <canvas id="canvas18" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas18");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'soft-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>difference</div>
+ <canvas id="canvas19" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas19");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'difference';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>exclusion</div>
+ <canvas id="canvas20" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas20");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'exclusion';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>hue</div>
+ <canvas id="canvas21" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas21");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hue';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>saturation</div>
+ <canvas id="canvas22" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas22");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'saturation';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color</div>
+ <canvas id="canvas23" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas23");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>luminosity</div>
+ <canvas id="canvas24" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas24");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'luminosity';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.globalCompositeOperation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.globalCompositeOperation.html
new file mode 100644
index 0000000000..32809d852c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.globalCompositeOperation.html
@@ -0,0 +1,861 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.globalCompositeOperation-expected.html">
+<title>Canvas test: 2d.layer.globalCompositeOperation</title>
+<h1 style="font-size: 20px;">2d.layer.globalCompositeOperation</h1>
+<p class="desc">Checks that layers work with all globalCompositeOperation values.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(7, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>source-over</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>source-in</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>source-atop</div>
+ <canvas id="canvas2" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas2");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>destination-over</div>
+ <canvas id="canvas3" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas3");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>destination-in</div>
+ <canvas id="canvas4" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas4");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>destination-out</div>
+ <canvas id="canvas5" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas5");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>destination-atop</div>
+ <canvas id="canvas6" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas6");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>lighter</div>
+ <canvas id="canvas7" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas7");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighter';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>copy</div>
+ <canvas id="canvas8" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas8");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>xor</div>
+ <canvas id="canvas9" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas9");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>multiply</div>
+ <canvas id="canvas10" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas10");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>screen</div>
+ <canvas id="canvas11" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas11");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'screen';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>overlay</div>
+ <canvas id="canvas12" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas12");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'overlay';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>darken</div>
+ <canvas id="canvas13" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas13");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'darken';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>lighten</div>
+ <canvas id="canvas14" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas14");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighten';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>color-dodge</div>
+ <canvas id="canvas15" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas15");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-dodge';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>color-burn</div>
+ <canvas id="canvas16" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas16");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-burn';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>hard-light</div>
+ <canvas id="canvas17" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas17");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hard-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>soft-light</div>
+ <canvas id="canvas18" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas18");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'soft-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>difference</div>
+ <canvas id="canvas19" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas19");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'difference';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>exclusion</div>
+ <canvas id="canvas20" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas20");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'exclusion';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>hue</div>
+ <canvas id="canvas21" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas21");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hue';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>saturation</div>
+ <canvas id="canvas22" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas22");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'saturation';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>color</div>
+ <canvas id="canvas23" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas23");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+<span>
+ <div>luminosity</div>
+ <canvas id="canvas24" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas24");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'luminosity';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ </script>
+</span>
+
+</div>
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
index 74e05e1e48..1544bbcb82 100644
--- 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
@@ -16,8 +16,9 @@
<ul id="d"></ul>
<script>
-var t = async_test("Raises exception on beginLayer() + reset() + endLayer().");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.beginLayer();
@@ -25,6 +26,6 @@ _addTest(function(canvas, ctx) {
ctx.endLayer();
});
-});
+}, "Raises exception on beginLayer() + reset() + 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
index 1979cb6c73..3d33fbf7fb 100644
--- 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
@@ -16,14 +16,15 @@
<ul id="d"></ul>
<script>
-var t = async_test("Raises exception on beginLayer() + restore().");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.beginLayer();
ctx.restore();
});
-});
+}, "Raises exception on beginLayer() + 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
index c635ac75b9..e48f806f32 100644
--- 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
@@ -16,8 +16,9 @@
<ul id="d"></ul>
<script>
-var t = async_test("Raises exception on beginLayer() + save() + endLayer().");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.beginLayer();
@@ -25,6 +26,6 @@ _addTest(function(canvas, ctx) {
ctx.endLayer();
});
-});
+}, "Raises exception on beginLayer() + save() + 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
index c39a352d65..2950de37bc 100644
--- 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
@@ -16,13 +16,14 @@
<ul id="d"></ul>
<script>
-var t = async_test("Raises exception on lone endLayer calls.");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.endLayer();
});
-});
+}, "Raises exception on lone endLayer calls.");
</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
index e2d4d56589..ff21610074 100644
--- 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
@@ -16,8 +16,9 @@
<ul id="d"></ul>
<script>
-var t = async_test("Raises exception on save() + beginLayer() + restore().");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.save();
@@ -25,6 +26,6 @@ _addTest(function(canvas, ctx) {
ctx.restore();
});
-});
+}, "Raises exception on save() + beginLayer() + 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
index f4308e1191..5c6da4b5bc 100644
--- 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
@@ -16,14 +16,15 @@
<ul id="d"></ul>
<script>
-var t = async_test("Raises exception on save() + endLayer().");
-_addTest(function(canvas, ctx) {
+test(t => {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.save();
ctx.endLayer();
});
-});
+}, "Raises exception on save() + endLayer().");
</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
deleted file mode 100644
index f1204aa61b..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.html
new file mode 100644
index 0000000000..8e81bffdfb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.html
@@ -0,0 +1,40 @@
+<!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</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">
+
+<script>
+
+promise_test(async t => {
+ const canvas = document.createElement('canvas');
+ const 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));
+}, "Throws if createImageBitmap is called while layers are open.");
+
+promise_test(async t => {
+ const canvas = document.createElement('canvas');
+ const 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)));
+}, "Throws if toBlob is called while layers are open.");
+
+</script>
+</div>
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
deleted file mode 100644
index 6c69bb3784..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.toBlob.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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
deleted file mode 100644
index f927b96524..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.createPattern.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!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
deleted file mode 100644
index 8bcc89d38e..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.drawImage.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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
deleted file mode 100644
index 5dc3fcc017..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.getImageData.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!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.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.html
new file mode 100644
index 0000000000..cf6e7a80db
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations</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">
+
+<script>
+
+test(t => {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ // 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'));
+}, "Throws if createPattern is called while layers are open.");
+
+test(t => {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ 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));
+}, "Throws if drawImage is called while layers are open.");
+
+test(t => {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ // 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));
+}, "Throws if getImageData is called while layers are open.");
+
+test(t => {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ 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));
+}, "Throws if putImageData is called while layers are open.");
+
+test(t => {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ // 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());
+}, "Throws if toDataURL is called while layers are open.");
+
+</script>
+</div>
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
deleted file mode 100644
index fd4fc262c2..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.putImageData.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!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
deleted file mode 100644
index c9bb4f3875..0000000000
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.toDataURL.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!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/manual/filters/svg-filter-lh-rlh-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-lh-rlh-expected.html
new file mode 100644
index 0000000000..d183f6940d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-lh-rlh-expected.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<title>HTML Canvas reference: SVG filter using CSS font-relative line-height units</title>
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+:root {
+ font: 20px Ahem;
+}
+
+div {
+ display: inline-block;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+
+.r {
+ background: red;
+}
+</style>
+<div><div class="r" style="width: 48px;"></div></div><br>
+<div><div class="r" style="width: 24px;"></div></div>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-lh-rlh.html b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-lh-rlh.html
new file mode 100644
index 0000000000..b61193fb9f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-lh-rlh.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<title>HTML Canvas test: SVG filter using CSS font-relative line-height units</title>
+<link rel="match" href="svg-filter-lh-rlh-expected.html"/>
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+:root {
+ font: 20px Ahem;
+}
+</style>
+<svg width="0" height="0">
+ <!-- https://html.spec.whatwg.org/multipage/canvas.html#working-with-externally-defined-svg-filters -->
+ <use href="./svg-filter.svg#filter-lh" />
+ <use href="./svg-filter.svg#filter-rlh" />
+</svg
+><canvas id="canvas-lh" width="100" height="100"></canvas><br
+><canvas id="canvas-rlh" width="100" height="100"></canvas>
+<script>
+function use_filter(canvas, filter_id) {
+ const ctx = canvas.getContext("2d");
+ ctx.font = "40px Ahem";
+ ctx.filter = `url(./svg-filter.svg#${filter_id})`;
+ ctx.fillStyle = "red";
+ ctx.fillRect(0, 0, 100, 100);
+}
+window.addEventListener("load", async () => {
+ use_filter(document.getElementById("canvas-lh"), "filter-lh");
+ use_filter(document.getElementById("canvas-rlh"), "filter-rlh");
+ document.documentElement.classList.remove('test-wait');
+});
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter.svg b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter.svg
new file mode 100644
index 0000000000..a783a3eb15
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter.svg
@@ -0,0 +1,10 @@
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
+ <filter id="filter-lh">
+ <feFlood result="floodFill" x="1lh" y="0" width="100" height="100" flood-color="green" />
+ <feBlend in="SourceGraphic" in2="floodFill" mode="color-dodge" />
+ </filter>
+ <filter id="filter-rlh">
+ <feFlood result="floodFill" x="1rlh" y="0" width="100" height="100" flood-color="green" />
+ <feBlend in="SourceGraphic" in2="floodFill" mode="color-dodge" />
+ </filter>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/text/WEB_FEATURES.yml b/testing/web-platform/tests/html/canvas/element/text/WEB_FEATURES.yml
new file mode 100644
index 0000000000..1d9e4bab82
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/text/WEB_FEATURES.yml
@@ -0,0 +1,4 @@
+features:
+- name: canvas-text-baselines
+ files:
+ - 2d.text.measure.baselines.*
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html
new file mode 100644
index 0000000000..69277677b9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-clamp-negative-saturation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.fillStyle.parse.hsl-clamp-negative-saturation</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<script>
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsl(120, -200%, 49.9%)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 127,127,127,255);
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.worker.js b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.worker.js
new file mode 100644
index 0000000000..7f1e91ddb7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.worker.js
@@ -0,0 +1,25 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.fillStyle.parse.hsl-clamp-negative-saturation
+// Description:
+// Note:<p class="notes">
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsl(120, -200%, 49.9%)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 127,127,127,255);
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html
new file mode 100644
index 0000000000..5d73d34c9c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-clamp-alpha-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.fillStyle.parse.hsla-clamp-alpha-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<script>
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsla(120, 100%, 50%, 2)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 0,255,0,255);
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.worker.js b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.worker.js
new file mode 100644
index 0000000000..7acb76d80b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.worker.js
@@ -0,0 +1,25 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.fillStyle.parse.hsla-clamp-alpha-1
+// Description:
+// Note:<p class="notes">
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsla(120, 100%, 50%, 2)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 0,255,0,255);
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html
new file mode 100644
index 0000000000..eaf7a6af89
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-clamp-alpha-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.fillStyle.parse.hsla-clamp-alpha-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<script>
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsla(120, 100%, 0%, -2)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 0,0,0,0);
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.worker.js b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.worker.js
new file mode 100644
index 0000000000..540b3ea15f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.worker.js
@@ -0,0 +1,25 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.fillStyle.parse.hsla-clamp-alpha-2
+// Description:
+// Note:<p class="notes">
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsla(120, 100%, 0%, -2)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 0,0,0,0);
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html
new file mode 100644
index 0000000000..04749fb4a7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-clamp-negative-saturation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.fillStyle.parse.hsla-clamp-negative-saturation</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<script>
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsla(120, -200%, 49.9%, 1)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 127,127,127,255);
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.worker.js b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.worker.js
new file mode 100644
index 0000000000..f5fe6d4296
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.worker.js
@@ -0,0 +1,25 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.fillStyle.parse.hsla-clamp-negative-saturation
+// Description:
+// Note:<p class="notes">
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'hsla(120, -200%, 49.9%, 1)';
+ ctx.fillRect(0, 0, 100, 50);
+ _assertPixel(canvas, 50,25, 127,127,127,255);
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
deleted file mode 100644
index dac31c97f1..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
deleted file mode 100644
index 801e6fdb8c..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.w.html
deleted file mode 100644
index 6c7c7f7649..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.w.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
deleted file mode 100644
index 88d0cb2de2..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 1" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
deleted file mode 100644
index ba986d8e7b..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 1],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.w.html
deleted file mode 100644
index 86fe086327..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.w.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 1],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
deleted file mode 100644
index 744983d4ae..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="1 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
deleted file mode 100644
index 0265cfa6c4..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [1, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.w.html
deleted file mode 100644
index c22b320857..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.w.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [1, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html
new file mode 100644
index 0000000000..c1ca0ab46f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative</title>
+<h1 style="font-size: 20px;">2d.filter.canvasFilterObject.gaussianBlur.tentative</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur0" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur0)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur1" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur1)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur2" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur2)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur3" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur3)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>y-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur4" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur4)" />
+ </svg>
+ </div>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
new file mode 100644
index 0000000000..8e7ea3f727
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative</title>
+<h1 style="font-size: 20px;">2d.filter.canvasFilterObject.gaussianBlur.tentative</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <canvas id="canvas0" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <canvas id="canvas1" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <canvas id="canvas2" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const outputCanvas = document.getElementById("canvas2");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <canvas id="canvas3" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const outputCanvas = document.getElementById("canvas3");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>y-only</div>
+ <canvas id="canvas4" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const outputCanvas = document.getElementById("canvas4");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.w.html
new file mode 100644
index 0000000000..71626ac46e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.w.html
@@ -0,0 +1,194 @@
+<!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.filter.canvasFilterObject.gaussianBlur.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative</title>
+<h1 style="font-size: 20px;">2d.filter.canvasFilterObject.gaussianBlur.tentative</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<script>pending_tests = 5;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <canvas id="canvas0" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <canvas id="canvas1" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <canvas id="canvas2" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker2" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker2').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas2');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <canvas id="canvas3" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker3" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker3').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas3');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>y-only</div>
+ <canvas id="canvas4" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker4" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker4').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas4');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
deleted file mode 100644
index e611113e42..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 0" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
deleted file mode 100644
index 3ed8e9ddf9..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 0],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.w.html
deleted file mode 100644
index 35cbc1b365..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.w.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [4, 0],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
deleted file mode 100644
index c6d915cb07..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="0 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
deleted file mode 100644
index f563ad9d77..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [0, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.w.html
deleted file mode 100644
index 171a41caa8..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.w.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
- name: 'gaussianBlur',
- stdDeviation: [0, 4],
- });
- ctx.fillRect(25, 25, 50, 50);
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur-expected.html
new file mode 100644
index 0000000000..f24e9d0dba
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur-expected.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur</title>
+<h1 style="font-size: 20px;">2d.filter.layers.gaussianBlur</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur0" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur0)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur1" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur1)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur2" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur2)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur3" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur3)" />
+ </svg>
+ </div>
+</span>
+
+<span>
+ <div>y-only</div>
+ <div style="width: 100px; height: 100px; outline: 1px solid">
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur4" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur4)" />
+ </svg>
+ </div>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.html
new file mode 100644
index 0000000000..a51fe32008
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur</title>
+<h1 style="font-size: 20px;">2d.filter.layers.gaussianBlur</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <canvas id="canvas0" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <canvas id="canvas1" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <canvas id="canvas2" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas2");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <canvas id="canvas3" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas3");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>y-only</div>
+ <canvas id="canvas4" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas4");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
deleted file mode 100644
index 4f93754862..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
-<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html
deleted file mode 100644
index 50a98df1be..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.isotropic-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
-<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html
deleted file mode 100644
index a68b8e78a2..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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.filter.layers.gaussianBlur.isotropic-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
-<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
deleted file mode 100644
index 255270c192..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 1" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html
deleted file mode 100644
index efc634796c..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-x-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 1],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html
deleted file mode 100644
index 7d20d78503..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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.filter.layers.gaussianBlur.mostly-x-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 1],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
deleted file mode 100644
index 76a46b1533..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="1 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html
deleted file mode 100644
index bdc6e66fe5..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-y-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [1, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html
deleted file mode 100644
index dfd6438b19..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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.filter.layers.gaussianBlur.mostly-y-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
-<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [1, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.w.html
new file mode 100644
index 0000000000..10ea8baa10
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.w.html
@@ -0,0 +1,199 @@
+<!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.filter.layers.gaussianBlur-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur</title>
+<h1 style="font-size: 20px;">2d.filter.layers.gaussianBlur</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<script>pending_tests = 5;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(5, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>x-only</div>
+ <canvas id="canvas0" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>mostly-x</div>
+ <canvas id="canvas1" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>isotropic</div>
+ <canvas id="canvas2" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker2" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker2').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas2');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>mostly-y</div>
+ <canvas id="canvas3" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker3" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker3').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas3');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>y-only</div>
+ <canvas id="canvas4" width="100" height="100" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker4" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker4').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas4');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
deleted file mode 100644
index 26741f9847..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
-<h1>2d.filter.layers.gaussianBlur.x-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="4 0" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html
deleted file mode 100644
index 0d42acb8b5..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.x-only-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
-<h1>2d.filter.layers.gaussianBlur.x-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 0],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html
deleted file mode 100644
index b235c7ad38..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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.filter.layers.gaussianBlur.x-only-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
-<h1>2d.filter.layers.gaussianBlur.x-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [4, 0],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
deleted file mode 100644
index d00eec6b57..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
-<h1>2d.filter.layers.gaussianBlur.y-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-
-<svg xmlns="http://www.w3.org/2000/svg"
- width="100" height="100"
- color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
- <feGaussianBlur stdDeviation="0 4" />
- </filter>
- <rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
-</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html
deleted file mode 100644
index c9bc85d699..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.layers.gaussianBlur.y-only-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
-<h1>2d.filter.layers.gaussianBlur.y-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script>
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [0, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html
deleted file mode 100644
index 5deb96c255..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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.filter.layers.gaussianBlur.y-only-expected.html">
-<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
-<h1>2d.filter.layers.gaussianBlur.y-only</h1>
-<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
-<canvas id="canvas" width="100" height="100">
- <p class="fallback">FAIL (fallback content)</p>
-</canvas>
-<script id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(100, 100);
- const ctx = canvas.getContext('2d');
-
- ctx.fillStyle = 'teal';
- ctx.beginLayer({filter: {
- name: 'gaussianBlur',
- stdDeviation: [0, 4],
- }});
- ctx.fillRect(25, 25, 50, 50);
- ctx.endLayer();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.html
index 4fb042a1d8..354a03a134 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Checks beginLayer works for different option parameter values");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -45,7 +39,6 @@ t.step(function() {
ctx.beginLayer({filter: 1}); ctx.endLayer();
ctx.beginLayer({filter: true}); ctx.endLayer();
ctx.beginLayer({filter: false}); ctx.endLayer();
- t.done();
-});
+}, "Checks beginLayer works for different option parameter values");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.worker.js
index cafbc83f3e..492ac3fcea 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Checks beginLayer works for different option parameter values");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -41,6 +35,5 @@ t.step(function() {
ctx.beginLayer({filter: 1}); ctx.endLayer();
ctx.beginLayer({filter: true}); ctx.endLayer();
ctx.beginLayer({filter: false}); ctx.endLayer();
- t.done();
-});
+}, "Checks beginLayer works for different option parameter values");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html
index b2306d95ac..919de40d2e 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Tests getTransform inside layers.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -26,7 +20,6 @@ t.step(function() {
const m = ctx.getTransform();
assert_array_equals([m.a, m.b, m.c, m.d, m.e, m.f], [2, 0, 0, 3, 10, 20]);
ctx.endLayer();
- t.done();
-});
+}, "Tests getTransform inside layers.");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js
index 54b1fee5d0..2d6e6ef8a2 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Tests getTransform inside layers.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -22,6 +16,5 @@ t.step(function() {
const m = ctx.getTransform();
assert_array_equals([m.a, m.b, m.c, m.d, m.e, m.f], [2, 0, 0, 3, 10, 20]);
ctx.endLayer();
- t.done();
-});
+}, "Tests getTransform inside layers.");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html
index a047c539cf..29b316b256 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Checks that the context state is left unchanged if beginLayer throws.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -26,7 +20,6 @@ t.step(function() {
values: 'foo'}}));
// `beginLayer` shouldn't have opened the layer, so `endLayer` should throw.
assert_throws_dom("InvalidStateError", () => ctx.endLayer());
- t.done();
-});
+}, "Checks that the context state is left unchanged if beginLayer throws.");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.worker.js
index bd1e376084..6e253b26d5 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Checks that the context state is left unchanged if beginLayer throws.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -22,6 +16,5 @@ t.step(function() {
values: 'foo'}}));
// `beginLayer` shouldn't have opened the layer, so `endLayer` should throw.
assert_throws_dom("InvalidStateError", () => ctx.endLayer());
- t.done();
-});
+}, "Checks that the context state is left unchanged if beginLayer throws.");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha-expected.html
deleted file mode 100644
index 0666e3098a..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.alpha.blending-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending-expected.html
deleted file mode 100644
index 8a45027588..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.alpha.blending.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.html
deleted file mode 100644
index 71414b4b37..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
deleted file mode 100644
index f7b633b35f..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.html
deleted file mode 100644
index ed2d2d70af..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.w.html
deleted file mode 100644
index 1ff3ad8385..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.w.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.w.html
deleted file mode 100644
index 618480c813..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.w.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite-expected.html
deleted file mode 100644
index 951049e638..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.alpha.composite.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.html
deleted file mode 100644
index 94fed5752d..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
deleted file mode 100644
index 0ae93871f5..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.html
deleted file mode 100644
index eb579cdcce..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.w.html
deleted file mode 100644
index 60e36f4b97..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.w.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.w.html
deleted file mode 100644
index d7d2b7a21e..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.w.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.html
deleted file mode 100644
index 63a264e681..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow-expected.html
deleted file mode 100644
index 6f764c5001..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.alpha.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.html
deleted file mode 100644
index 65a66c977d..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.w.html
deleted file mode 100644
index f404601e3d..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.w.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.w.html
deleted file mode 100644
index 694f31e208..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.w.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending-expected.html
deleted file mode 100644
index 33fdf46a28..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.blending.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.html
deleted file mode 100644
index 6a36bb4ba1..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..c56f13f2fd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.html
new file mode 100644
index 0000000000..1f8736e0e4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..2bd46eee66
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.blending.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..e5f8ba0db4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.html
new file mode 100644
index 0000000000..0470777988
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..4d33b3a638
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.blending.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow-expected.html
deleted file mode 100644
index 6f969074f9..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.blending.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.html
deleted file mode 100644
index 2e91f3d2d1..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..debbd430c4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.html
new file mode 100644
index 0000000000..c6f0239c39
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.w.html
new file mode 100644
index 0000000000..0be246ebfb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.blending.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation-expected.html
new file mode 100644
index 0000000000..75a55e591b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.html
new file mode 100644
index 0000000000..aac9d86e66
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.w.html
new file mode 100644
index 0000000000..86067b7299
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.blending.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.w.html
deleted file mode 100644
index d8e20d0479..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.w.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.w.html
deleted file mode 100644
index 8964e97713..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.w.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite-expected.html
deleted file mode 100644
index ed7669c4cf..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.composite.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.html
deleted file mode 100644
index 84fb4b3d95..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..cf87559582
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.html
new file mode 100644
index 0000000000..69dc916d7d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..aa358b57bc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.composite.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..2f9bb208fb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.html
new file mode 100644
index 0000000000..d0d08f9835
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..5e2cd0783d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.composite.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow-expected.html
deleted file mode 100644
index b687c27f47..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.composite.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.html
deleted file mode 100644
index 1e3ab4d6a0..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..2b4436806a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.html
new file mode 100644
index 0000000000..8b79eba128
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.w.html
new file mode 100644
index 0000000000..47f2df391f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.composite.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation-expected.html
new file mode 100644
index 0000000000..da144975a5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.html
new file mode 100644
index 0000000000..632d390986
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.w.html
new file mode 100644
index 0000000000..dde0d8bec0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.composite.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.w.html
deleted file mode 100644
index 7dfb70148b..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.w.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.w.html
deleted file mode 100644
index b695871fcd..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.w.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..489d432282
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.html
new file mode 100644
index 0000000000..70b659f52b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..1db7f17a94
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.copy.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..63913ffb05
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.html
new file mode 100644
index 0000000000..2151535015
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..9c0cac99b9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.copy.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..021581f892
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.html
new file mode 100644
index 0000000000..42231fa61e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.w.html
new file mode 100644
index 0000000000..20dc667ef8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.copy.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation-expected.html
new file mode 100644
index 0000000000..dd9a5c2a00
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.html
new file mode 100644
index 0000000000..77158a9f96
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.copy.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.w.html
new file mode 100644
index 0000000000..def6bc51e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.copy.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.copy.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha-expected.html
deleted file mode 100644
index f304700feb..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.alpha.blending-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending-expected.html
deleted file mode 100644
index 7c91ce4229..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending-expected.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html
deleted file mode 100644
index 0e48cb49f7..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-2453">
-<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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
deleted file mode 100644
index 62942ffeae..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
deleted file mode 100644
index 62d98d967c..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.w.html
deleted file mode 100644
index e81efd6b8d..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.w.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html
deleted file mode 100644
index 3887ed4485..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!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.global-states.filter.alpha.blending-expected.html">
-<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-2453">
-<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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite-expected.html
deleted file mode 100644
index 8e0d98648e..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite-expected.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html
deleted file mode 100644
index 1a9bc8b733..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-5204">
-<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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
deleted file mode 100644
index a649972546..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
deleted file mode 100644
index d067ff2f5e..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.w.html
deleted file mode 100644
index 39abc78b17..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.w.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html
deleted file mode 100644
index 5c90fe95aa..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!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.global-states.filter.alpha.composite-expected.html">
-<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-5204">
-<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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html
deleted file mode 100644
index f64e8925f0..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6766">
-<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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
deleted file mode 100644
index 169baee29b..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html
deleted file mode 100644
index 5e8911ee17..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!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">
-<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6311">
-<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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html
deleted file mode 100644
index b3be7e1ac8..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!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.global-states.filter.alpha.shadow-expected.html">
-<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6311">
-<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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html
deleted file mode 100644
index 21e55f856c..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!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.global-states.filter.alpha-expected.html">
-<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6766">
-<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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending-expected.html
deleted file mode 100644
index f81dcf72dc..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.blending.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.html
deleted file mode 100644
index ce2b046798..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..482ab25a85
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!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.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html
new file mode 100644
index 0000000000..8acbfa668f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..93edfabdf3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.filter.blending.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..3af6b863ed
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!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.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html
new file mode 100644
index 0000000000..0a4a8c65d2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..7caaf1edee
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.filter.blending.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow-expected.html
deleted file mode 100644
index 91f3725f8e..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow-expected.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.blending.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.html
deleted file mode 100644
index d0d429bee3..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..d530ef9d19
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html
new file mode 100644
index 0000000000..1ee3254324
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.w.html
new file mode 100644
index 0000000000..3ec656c135
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.filter.blending.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html
new file mode 100644
index 0000000000..80705c36fd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.html
new file mode 100644
index 0000000000..62af08d2ac
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.w.html
new file mode 100644
index 0000000000..d5693cdcdc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.filter.blending.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.blending.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.w.html
deleted file mode 100644
index ce432ea74d..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.w.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.w.html
deleted file mode 100644
index bb101cdc0b..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.w.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite-expected.html
deleted file mode 100644
index 97e85a1593..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.composite.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.html
deleted file mode 100644
index 32052a1150..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..2f513bff0a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!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.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html
new file mode 100644
index 0000000000..17394aa4c8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!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.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..386ad43b0f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.filter.composite.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..242973300f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!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.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html
new file mode 100644
index 0000000000..576283ea73
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!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.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..6dd39d77e9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.filter.composite.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow-expected.html
deleted file mode 100644
index 4716bb2760..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow-expected.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.composite.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.html
deleted file mode 100644
index b5e8b9f843..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..c8926e5e15
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!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.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html
new file mode 100644
index 0000000000..b574a819d6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!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.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.w.html
new file mode 100644
index 0000000000..96ee1b027b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.filter.composite.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html
new file mode 100644
index 0000000000..e70fe3e92d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!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.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.html
new file mode 100644
index 0000000000..b7b4312a35
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!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.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.w.html
new file mode 100644
index 0000000000..1ae9f00a85
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.filter.composite.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.composite.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.w.html
deleted file mode 100644
index 894089d88e..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.w.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.w.html
deleted file mode 100644
index 41ccdaf5c0..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.w.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..21aa241aca
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html
new file mode 100644
index 0000000000..f08ba940af
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!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.copy.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..75fc90bae6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.filter.copy.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..b2b46ee039
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html
new file mode 100644
index 0000000000..3f12cf0c4e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!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.copy.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..0a3ecee669
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.filter.copy.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..d11326d5d6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html
new file mode 100644
index 0000000000..b4996deb6f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!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.copy.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.w.html
new file mode 100644
index 0000000000..9c13a367b3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.filter.copy.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html
new file mode 100644
index 0000000000..3ac098c344
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.html
new file mode 100644
index 0000000000..eab5f8312b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!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.copy.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.w.html
new file mode 100644
index 0000000000..aebd6cc00d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.copy.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.filter.copy.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.copy.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.copy.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..a445ae2c4a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html
@@ -0,0 +1,98 @@
+<!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-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html
new file mode 100644
index 0000000000..f86b0fd37d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!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-composite-op.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..ab0836af94
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.filter.no-composite-op.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..610c601b1c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation-expected.html
@@ -0,0 +1,102 @@
+<!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-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html
new file mode 100644
index 0000000000..5854af853c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!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-composite-op.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..c08f1f9f3c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.filter.no-composite-op.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..6bd4501584
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform-expected.html
@@ -0,0 +1,104 @@
+<!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-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html
new file mode 100644
index 0000000000..f1dc725b83
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!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-composite-op.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.w.html
new file mode 100644
index 0000000000..f191747805
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.filter.no-composite-op.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html
new file mode 100644
index 0000000000..b60a5526d9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation-expected.html
@@ -0,0 +1,108 @@
+<!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-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="90" height="90"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.8"></feFuncA>
+ </feComponentTransfer>
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 90;
+ img.height = 90;
+ img.onload = () => {
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html
new file mode 100644
index 0000000000..76258b326d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!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-composite-op.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.w.html
new file mode 100644
index 0000000000..9a10fb569f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-composite-op.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.filter.no-composite-op.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.filter.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
+
+ ctx.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states-expected.html
deleted file mode 100644
index e56fe0b360..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states-expected.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.no-global-states.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.html
deleted file mode 100644
index 3effa3ee9d..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.w.html
deleted file mode 100644
index ec744d7ffe..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.w.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow-expected.html
deleted file mode 100644
index 13ba2dd4cd..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow-expected.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.filter.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.html
deleted file mode 100644
index 7bb0ef5e13..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.w.html
deleted file mode 100644
index bc9bd48aad..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.w.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform-expected.html
new file mode 100644
index 0000000000..d1a799707f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform-expected.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html
new file mode 100644
index 0000000000..016f78a5d8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.html
@@ -0,0 +1,85 @@
+<!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-composite-op.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.w.html
new file mode 100644
index 0000000000..2a450624f1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.no-transform.w.html
@@ -0,0 +1,116 @@
+<!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.global-states.no-composite-op.no-shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html
new file mode 100644
index 0000000000..cc91a67faf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation-expected.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html
new file mode 100644
index 0000000000..12a1e64b42
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.html
@@ -0,0 +1,89 @@
+<!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-composite-op.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.w.html
new file mode 100644
index 0000000000..a0f5f76099
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.no-shadow.rotation.w.html
@@ -0,0 +1,120 @@
+<!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.global-states.no-composite-op.no-shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.no-shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.no-shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ // No shadow.
+
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html
new file mode 100644
index 0000000000..02b239116c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform-expected.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html
new file mode 100644
index 0000000000..99301fde09
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.html
@@ -0,0 +1,91 @@
+<!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-composite-op.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.w.html
new file mode 100644
index 0000000000..46375f290c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.no-transform.w.html
@@ -0,0 +1,122 @@
+<!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.global-states.no-composite-op.shadow.no-transform-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.no-transform</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.no-transform</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ // No transform.
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html
new file mode 100644
index 0000000000..06f6a2dff3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation-expected.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(30, 5, 50, 40);
+
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html
new file mode 100644
index 0000000000..280cc1cceb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.html
@@ -0,0 +1,95 @@
+<!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-composite-op.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.w.html
new file mode 100644
index 0000000000..3192f79afa
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-composite-op.shadow.rotation.w.html
@@ -0,0 +1,126 @@
+<!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.global-states.no-composite-op.shadow.rotation-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-composite-op.shadow.rotation</title>
+<h1 style="font-size: 20px;">2d.layer.global-states.no-composite-op.shadow.rotation</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<script>pending_tests = 2;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(2, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>no-globalAlpha</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ // No globalAlpha.
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>globalAlpha</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ // No globalCompositeOperation.
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
+ 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states-expected.html
deleted file mode 100644
index b91a2ae8b5..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.no-global-states.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.html
deleted file mode 100644
index c8a9815381..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.w.html
deleted file mode 100644
index db03a3fd0c..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.w.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow-expected.html
deleted file mode 100644
index 835e9d420a..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!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/offscreen/layers/2d.layer.global-states.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.html
deleted file mode 100644
index ad60e87fb1..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!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 = new OffscreenCanvas(200, 200);
- 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();
-
- const outputCanvas = document.getElementById("canvas");
- outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.w.html
deleted file mode 100644
index 1fc35fd33a..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.w.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!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.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 id='myWorker' type='text/worker'>
- self.onmessage = function(e) {
- const canvas = new OffscreenCanvas(200, 200);
- 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();
-
- const bitmap = canvas.transferToImageBitmap();
- self.postMessage(bitmap, bitmap);
- };
-</script>
-<script>
- const blob = new Blob([document.getElementById('myWorker').textContent]);
- const worker = new Worker(URL.createObjectURL(blob));
- worker.addEventListener('message', msg => {
- const outputCtx = document.getElementById("canvas").getContext('2d');
- outputCtx.drawImage(msg.data, 0, 0);
- document.documentElement.classList.remove("reftest-wait");
- });
- worker.postMessage(null);
-</script>
-</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation-expected.html
new file mode 100644
index 0000000000..02a8915c0b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation-expected.html
@@ -0,0 +1,910 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.globalCompositeOperation</title>
+<h1 style="font-size: 20px;">2d.layer.globalCompositeOperation</h1>
+<p class="desc">Checks that layers work with all globalCompositeOperation values.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(7, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>source-over</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas0");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>source-in</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas1");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>source-atop</div>
+ <canvas id="canvas2" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas2");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-over</div>
+ <canvas id="canvas3" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas3");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-in</div>
+ <canvas id="canvas4" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas4");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-out</div>
+ <canvas id="canvas5" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas5");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-atop</div>
+ <canvas id="canvas6" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas6");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>lighter</div>
+ <canvas id="canvas7" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas7");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighter';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>copy</div>
+ <canvas id="canvas8" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas8");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>xor</div>
+ <canvas id="canvas9" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas9");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>multiply</div>
+ <canvas id="canvas10" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas10");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>screen</div>
+ <canvas id="canvas11" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas11");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'screen';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>overlay</div>
+ <canvas id="canvas12" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas12");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'overlay';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>darken</div>
+ <canvas id="canvas13" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas13");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'darken';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>lighten</div>
+ <canvas id="canvas14" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas14");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighten';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color-dodge</div>
+ <canvas id="canvas15" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas15");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-dodge';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color-burn</div>
+ <canvas id="canvas16" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas16");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-burn';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>hard-light</div>
+ <canvas id="canvas17" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas17");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hard-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>soft-light</div>
+ <canvas id="canvas18" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas18");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'soft-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>difference</div>
+ <canvas id="canvas19" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas19");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'difference';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>exclusion</div>
+ <canvas id="canvas20" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas20");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'exclusion';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>hue</div>
+ <canvas id="canvas21" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas21");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hue';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>saturation</div>
+ <canvas id="canvas22" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas22");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'saturation';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color</div>
+ <canvas id="canvas23" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas23");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>luminosity</div>
+ <canvas id="canvas24" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas24");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'luminosity';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.html
new file mode 100644
index 0000000000..ab9bc4270b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.html
@@ -0,0 +1,961 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.globalCompositeOperation-expected.html">
+<title>Canvas test: 2d.layer.globalCompositeOperation</title>
+<h1 style="font-size: 20px;">2d.layer.globalCompositeOperation</h1>
+<p class="desc">Checks that layers work with all globalCompositeOperation values.</p>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(7, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>source-over</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas0");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>source-in</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas1");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>source-atop</div>
+ <canvas id="canvas2" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas2");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-over</div>
+ <canvas id="canvas3" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas3");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-in</div>
+ <canvas id="canvas4" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas4");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-out</div>
+ <canvas id="canvas5" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas5");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>destination-atop</div>
+ <canvas id="canvas6" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas6");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>lighter</div>
+ <canvas id="canvas7" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighter';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas7");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>copy</div>
+ <canvas id="canvas8" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas8");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>xor</div>
+ <canvas id="canvas9" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas9");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>multiply</div>
+ <canvas id="canvas10" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas10");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>screen</div>
+ <canvas id="canvas11" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'screen';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas11");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>overlay</div>
+ <canvas id="canvas12" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'overlay';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas12");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>darken</div>
+ <canvas id="canvas13" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'darken';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas13");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>lighten</div>
+ <canvas id="canvas14" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighten';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas14");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color-dodge</div>
+ <canvas id="canvas15" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-dodge';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas15");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color-burn</div>
+ <canvas id="canvas16" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-burn';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas16");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>hard-light</div>
+ <canvas id="canvas17" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hard-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas17");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>soft-light</div>
+ <canvas id="canvas18" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'soft-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas18");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>difference</div>
+ <canvas id="canvas19" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'difference';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas19");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>exclusion</div>
+ <canvas id="canvas20" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'exclusion';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas20");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>hue</div>
+ <canvas id="canvas21" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hue';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas21");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>saturation</div>
+ <canvas id="canvas22" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'saturation';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas22");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>color</div>
+ <canvas id="canvas23" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas23");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+<span>
+ <div>luminosity</div>
+ <canvas id="canvas24" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'luminosity';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas24");
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(canvas, 0, 0);
+ </script>
+</span>
+
+</div>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.w.html
new file mode 100644
index 0000000000..9a403140fc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.globalCompositeOperation.w.html
@@ -0,0 +1,1314 @@
+<!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.globalCompositeOperation-expected.html">
+<title>Canvas test: 2d.layer.globalCompositeOperation</title>
+<h1 style="font-size: 20px;">2d.layer.globalCompositeOperation</h1>
+<p class="desc">Checks that layers work with all globalCompositeOperation values.</p>
+<script>pending_tests = 25;</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat(7, max-content);
+ font-size: 13px; text-align: center;">
+<span>
+ <div>source-over</div>
+ <canvas id="canvas0" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker0" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker0').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas0');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>source-in</div>
+ <canvas id="canvas1" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker1" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker1').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas1');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>source-atop</div>
+ <canvas id="canvas2" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker2" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'source-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker2').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas2');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>destination-over</div>
+ <canvas id="canvas3" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker3" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-over';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker3').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas3');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>destination-in</div>
+ <canvas id="canvas4" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker4" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-in';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker4').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas4');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>destination-out</div>
+ <canvas id="canvas5" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker5" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker5').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas5');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>destination-atop</div>
+ <canvas id="canvas6" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker6" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker6').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas6');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>lighter</div>
+ <canvas id="canvas7" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker7" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighter';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker7').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas7');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>copy</div>
+ <canvas id="canvas8" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker8" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'copy';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker8').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas8');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>xor</div>
+ <canvas id="canvas9" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker9" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker9').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas9');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>multiply</div>
+ <canvas id="canvas10" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker10" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker10').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas10');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>screen</div>
+ <canvas id="canvas11" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker11" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'screen';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker11').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas11');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>overlay</div>
+ <canvas id="canvas12" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker12" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'overlay';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker12').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas12');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>darken</div>
+ <canvas id="canvas13" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker13" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'darken';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker13').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas13');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>lighten</div>
+ <canvas id="canvas14" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker14" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'lighten';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker14').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas14');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>color-dodge</div>
+ <canvas id="canvas15" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker15" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-dodge';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker15').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas15');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>color-burn</div>
+ <canvas id="canvas16" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker16" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color-burn';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker16').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas16');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>hard-light</div>
+ <canvas id="canvas17" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker17" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hard-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker17').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas17');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>soft-light</div>
+ <canvas id="canvas18" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker18" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'soft-light';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker18').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas18');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>difference</div>
+ <canvas id="canvas19" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker19" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'difference';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker19').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas19');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>exclusion</div>
+ <canvas id="canvas20" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker20" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'exclusion';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker20').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas20');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>hue</div>
+ <canvas id="canvas21" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker21" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'hue';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker21').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas21');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>saturation</div>
+ <canvas id="canvas22" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker22" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'saturation';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker22').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas22');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>color</div>
+ <canvas id="canvas23" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker23" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'color';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker23').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas23');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+<span>
+ <div>luminosity</div>
+ <canvas id="canvas24" width="90" height="90" style="outline: 1px solid">
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker24" type="text/worker">
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(90, 90);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = 'luminosity';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker24').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas24');
+ const outputCtx = outputCanvas.getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html
index c0b11aa611..e588e48b5f 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Raises exception on beginLayer() + reset() + endLayer().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -25,7 +19,6 @@ t.step(function() {
ctx.reset();
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on beginLayer() + reset() + endLayer().");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.worker.js
index 1c147d6f34..cab1b9d92d 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Raises exception on beginLayer() + reset() + endLayer().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -21,6 +15,5 @@ t.step(function() {
ctx.reset();
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on beginLayer() + reset() + endLayer().");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.html
index 022532b329..30a981f75a 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Raises exception on beginLayer() + restore().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -24,7 +18,6 @@ t.step(function() {
ctx.beginLayer();
ctx.restore();
});
- t.done();
-});
+}, "Raises exception on beginLayer() + restore().");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.worker.js
index 1aa86635e6..287f8eb004 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Raises exception on beginLayer() + restore().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -20,6 +14,5 @@ t.step(function() {
ctx.beginLayer();
ctx.restore();
});
- t.done();
-});
+}, "Raises exception on beginLayer() + restore().");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html
index 26dd0eee4b..04992b115e 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Raises exception on beginLayer() + save() + endLayer().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -25,7 +19,6 @@ t.step(function() {
ctx.save();
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on beginLayer() + save() + endLayer().");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.worker.js
index 613921c67c..402bf5e0fd 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Raises exception on beginLayer() + save() + endLayer().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -21,6 +15,5 @@ t.step(function() {
ctx.save();
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on beginLayer() + save() + endLayer().");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.html
index 440249980a..5b7f8a851e 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.html
@@ -10,20 +10,13 @@
<script>
-var t = async_test("Raises exception on lone endLayer calls.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on lone endLayer calls.");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.worker.js
index b2ba231b9c..2229aa9628 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.worker.js
@@ -6,19 +6,12 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Raises exception on lone endLayer calls.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
assert_throws_dom("INVALID_STATE_ERR", function() {
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on lone endLayer calls.");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.html
index c2b09961ac..2a6c9b1ccb 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Raises exception on save() + beginLayer() + restore().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -25,7 +19,6 @@ t.step(function() {
ctx.beginLayer();
ctx.restore();
});
- t.done();
-});
+}, "Raises exception on save() + beginLayer() + restore().");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.worker.js
index d155379fcb..711280a6de 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Raises exception on save() + beginLayer() + restore().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -21,6 +15,5 @@ t.step(function() {
ctx.beginLayer();
ctx.restore();
});
- t.done();
-});
+}, "Raises exception on save() + beginLayer() + restore().");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.html
index 01b62d1e85..32ca134663 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.html
@@ -10,13 +10,7 @@
<script>
-var t = async_test("Raises exception on save() + endLayer().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -24,7 +18,6 @@ t.step(function() {
ctx.save();
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on save() + endLayer().");
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.worker.js
index 353c1b00cd..af3667e50a 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.worker.js
@@ -6,13 +6,7 @@
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Raises exception on save() + endLayer().");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
+test(t => {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
@@ -20,6 +14,5 @@ t.step(function() {
ctx.save();
ctx.endLayer();
});
- t.done();
-});
+}, "Raises exception on save() + endLayer().");
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.html
deleted file mode 100644
index 0b3854c31d..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas test: 2d.layer.malformed-operations-with-promises.convertToBlob</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-
-<h1>2d.layer.malformed-operations-with-promises.convertToBlob</h1>
-<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
-
-
-<script>
-promise_test(async t => {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // Shouldn't throw on its own.
- await canvas.convertToBlob();
- // Make sure the exception isn't caused by calling the function twice.
- await canvas.convertToBlob();
- // Calling again inside a layer should throw.
- ctx.beginLayer();
- await promise_rejects_dom(t, 'InvalidStateError', canvas.convertToBlob());
-
-}, "Check that exceptions are thrown for operations that are malformed while layers are open.");
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.worker.js
deleted file mode 100644
index 8361e19108..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.worker.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.layer.malformed-operations-with-promises.convertToBlob
-// Description:Check that exceptions are thrown for operations that are malformed while layers are open.
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-promise_test(async t => {
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // Shouldn't throw on its own.
- await canvas.convertToBlob();
- // Make sure the exception isn't caused by calling the function twice.
- await canvas.convertToBlob();
- // Calling again inside a layer should throw.
- ctx.beginLayer();
- await promise_rejects_dom(t, 'InvalidStateError', canvas.convertToBlob());
-}, "Check that exceptions are thrown for operations that are malformed while layers are open.");
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html
deleted file mode 100644
index 085554d9f5..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas 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>
-
-<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>
-
-
-<script>
-promise_test(async t => {
-
- var canvas = new OffscreenCanvas(200, 200);
- 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/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.worker.js
deleted file mode 100644
index d64f693864..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.worker.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.layer.malformed-operations-with-promises.createImageBitmap
-// Description:Check that exceptions are thrown for operations that are malformed while layers are open.
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-promise_test(async t => {
- var canvas = new OffscreenCanvas(200, 200);
- 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.");
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.html
new file mode 100644
index 0000000000..7b8f9b0943
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.malformed-operations-with-promises</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<script>
+
+promise_test(async t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // Shouldn't throw on its own.
+ await canvas.convertToBlob();
+ // Make sure the exception isn't caused by calling the function twice.
+ await canvas.convertToBlob();
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ await promise_rejects_dom(t, 'InvalidStateError',
+ canvas.convertToBlob());
+}, "Throws if convertToBlob is called while layers are open.");
+
+promise_test(async t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const 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));
+}, "Throws if createImageBitmap is called while layers are open.");
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.worker.js
new file mode 100644
index 0000000000..693901b648
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.worker.js
@@ -0,0 +1,37 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.malformed-operations-with-promises
+// Description:
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+promise_test(async t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // Shouldn't throw on its own.
+ await canvas.convertToBlob();
+ // Make sure the exception isn't caused by calling the function twice.
+ await canvas.convertToBlob();
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ await promise_rejects_dom(t, 'InvalidStateError',
+ canvas.convertToBlob());
+}, "Throws if convertToBlob is called while layers are open.");
+
+promise_test(async t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const 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));
+}, "Throws if createImageBitmap is called while layers are open.");
+
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.html
deleted file mode 100644
index a206e64ceb..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas 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>
-
-<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>
-
-
-<script>
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // 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'));
- t.done();
-
-});
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.worker.js
deleted file mode 100644
index bcb42cba87..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.worker.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.layer.malformed-operations.createPattern
-// Description:Check that exceptions are thrown for operations that are malformed while layers are open.
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // 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'));
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.html
deleted file mode 100644
index e6a9872100..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas 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>
-
-<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>
-
-
-<script>
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- 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));
- t.done();
-
-});
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.worker.js
deleted file mode 100644
index b66cdee62e..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.worker.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.layer.malformed-operations.drawImage
-// Description:Check that exceptions are thrown for operations that are malformed while layers are open.
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- 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));
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.html
deleted file mode 100644
index 87bc8c6ede..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas 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>
-
-<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>
-
-
-<script>
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // 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));
- t.done();
-
-});
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.worker.js
deleted file mode 100644
index 6a1a16fccb..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.worker.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.layer.malformed-operations.getImageData
-// Description:Check that exceptions are thrown for operations that are malformed while layers are open.
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // 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));
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.html
new file mode 100644
index 0000000000..a810665faf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.malformed-operations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<script>
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // 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'));
+}, "Throws if createPattern is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ 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));
+}, "Throws if drawImage is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // 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));
+}, "Throws if getImageData is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ 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));
+}, "Throws if putImageData is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // Shouldn't throw on its own.
+ canvas.transferToImageBitmap();
+ // Make sure the exception isn't caused by calling the function twice.
+ canvas.transferToImageBitmap();
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => canvas.transferToImageBitmap());
+}, "Throws if transferToImageBitmap is called while layers are open.");
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.html
deleted file mode 100644
index e8059076bb..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas 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>
-
-<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>
-
-
-<script>
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- 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));
- t.done();
-
-});
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.worker.js
deleted file mode 100644
index 8810c3a73c..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.worker.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.layer.malformed-operations.putImageData
-// Description:Check that exceptions are thrown for operations that are malformed while layers are open.
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- 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));
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.html
deleted file mode 100644
index 79c216421f..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas test: 2d.layer.malformed-operations.transferToImageBitmap</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-
-<h1>2d.layer.malformed-operations.transferToImageBitmap</h1>
-<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
-
-
-<script>
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // Shouldn't throw on its own.
- canvas.transferToImageBitmap();
- // Make sure the exception isn't caused by calling the function twice.
- canvas.transferToImageBitmap();
- // Calling again inside a layer should throw.
- ctx.beginLayer();
- assert_throws_dom("InvalidStateError",
- () => canvas.transferToImageBitmap());
- t.done();
-
-});
-</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.worker.js
deleted file mode 100644
index be0b43665a..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.worker.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.layer.malformed-operations.transferToImageBitmap
-// Description:Check that exceptions are thrown for operations that are malformed while layers are open.
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
-var t_pass = t.done.bind(t);
-var t_fail = t.step_func(function(reason) {
- throw reason;
-});
-t.step(function() {
-
- var canvas = new OffscreenCanvas(200, 200);
- var ctx = canvas.getContext('2d');
-
- // Shouldn't throw on its own.
- canvas.transferToImageBitmap();
- // Make sure the exception isn't caused by calling the function twice.
- canvas.transferToImageBitmap();
- // Calling again inside a layer should throw.
- ctx.beginLayer();
- assert_throws_dom("InvalidStateError",
- () => canvas.transferToImageBitmap());
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.worker.js
new file mode 100644
index 0000000000..5851fcfbc6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.worker.js
@@ -0,0 +1,84 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.malformed-operations
+// Description:
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // 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'));
+}, "Throws if createPattern is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ 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));
+}, "Throws if drawImage is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // 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));
+}, "Throws if getImageData is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ 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));
+}, "Throws if putImageData is called while layers are open.");
+
+test(t => {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // Shouldn't throw on its own.
+ canvas.transferToImageBitmap();
+ // Make sure the exception isn't caused by calling the function twice.
+ canvas.transferToImageBitmap();
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => canvas.transferToImageBitmap());
+}, "Throws if transferToImageBitmap is called while layers are open.");
+
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/text/WEB_FEATURES.yml b/testing/web-platform/tests/html/canvas/offscreen/text/WEB_FEATURES.yml
new file mode 100644
index 0000000000..1d9e4bab82
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/text/WEB_FEATURES.yml
@@ -0,0 +1,4 @@
+features:
+- name: canvas-text-baselines
+ files:
+ - 2d.text.measure.baselines.*
diff --git a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py
index 57077f6057..415090a14a 100644
--- a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py
+++ b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py
@@ -345,17 +345,43 @@ class _Variant():
'desc': '',
'size': [100, 50],
'variant_names': [],
+ 'grid_variant_names': [],
+ 'images': [],
+ 'svgimages': [],
}
params.update(test)
return _Variant(params)
- def _get_variant_name(self, jinja_env: jinja2.Environment) -> str:
- name = self.params['name']
+ def merge_params(self, params: _TestParams) -> '_Variant':
+ """Returns a new `_Variant` that merges `self.params` and `params`."""
+ new_params = {}
+ new_params.update(self.params)
+ new_params.update(params)
+ return _Variant(new_params)
+
+ def with_grid_variant_name(self, name: str) -> '_Variant':
+ """Addend a variant name to include in the grid element label."""
+ self._params.update({
+ 'variant_names': (self.params['variant_names'] + [name]),
+ 'grid_variant_names': (self.params['grid_variant_names'] + [name]),
+ })
+ return self
+
+ def with_file_variant_name(self, name: str) -> '_Variant':
+ """Addend a variant name to include in the generated file name."""
+ self._params.update({
+ 'variant_names': (self.params['variant_names'] + [name]),
+ })
if self.params.get('append_variants_to_name', True):
- name = '.'.join([name] + self.params['variant_names'])
+ self._params['name'] = self.params['name'] + '.' + name
+ return self
+
+ def _render_param(self, jinja_env: jinja2.Environment,
+ param_name: str) -> str:
+ """Get the specified variant parameter and render it with Jinja."""
+ value = self.params[param_name]
+ return jinja_env.from_string(value).render(self.params)
- name = jinja_env.from_string(name).render(self.params)
- return name
def _get_file_name(self) -> str:
file_name = self.params['name']
@@ -389,9 +415,12 @@ class _Variant():
return _TemplateType.HTML_REFERENCE
return _TemplateType.TESTHARNESS
- def finalize_params(self, jinja_env: jinja2.Environment) -> None:
+ def finalize_params(self, jinja_env: jinja2.Environment,
+ variant_id: int) -> None:
"""Finalize this variant by adding computed param fields."""
- self._params['name'] = self._get_variant_name(jinja_env)
+ self._params['id'] = variant_id
+ self._params['name'] = self._render_param(jinja_env, 'name')
+ self._params['desc'] = self._render_param(jinja_env, 'desc')
self._params['file_name'] = self._get_file_name()
self._params['canvas_types'] = self._get_canvas_types()
self._params['template_type'] = self._get_template_type()
@@ -461,103 +490,282 @@ class _Variant():
self._params['expected_img'] = f'{name}.png'
+
+class _VariantGrid:
+
+ def __init__(self, variants: List[_Variant], grid_width: int) -> None:
+ self._variants = variants
+ self._grid_width = grid_width
+
+ self._file_name = None
+ self._canvas_types = None
+ self._template_type = None
+ self._params = None
+
+ @property
+ def variants(self) -> List[_Variant]:
+ """Read only getter for the list of variant in this grid."""
+ return self._variants
+
+ @property
+ def file_name(self):
+ """File name to which this grid will be written."""
+ if self._file_name is None:
+ self._file_name = self._unique_param('file_name')
+ return self._file_name
+
+ @property
+ def canvas_types(self) -> FrozenSet[_CanvasType]:
+ """Returns the set of all _CanvasType used by this grid's variants."""
+ if self._canvas_types is None:
+ self._canvas_types = self._param_set('canvas_types')
+ return self._canvas_types
+
+ @property
+ def template_type(self) -> _TemplateType:
+ """Returns the type of Jinja template needed to render this grid."""
+ if self._template_type is None:
+ self._template_type = self._unique_param('template_type')
+ return self._template_type
+
+ @property
+ def params(self) -> _TestParams:
+ """Returns this grid's param dict, used to render Jinja templates."""
+ if self._params is None:
+ if len(self.variants) == 1:
+ self._params = dict(self.variants[0].params)
+ else:
+ self._params = self._get_grid_params()
+ return self._params
+
+ def finalize(self, jinja_env: jinja2.Environment):
+ """Finalize this grid's variants, adding computed params fields."""
+ for variant_id, variant in enumerate(self.variants):
+ variant.finalize_params(jinja_env, variant_id)
+
+ def add_dimension(self, variants: Mapping[str,
+ _TestParams]) -> '_VariantGrid':
+ """Adds a variant dimension to this variant grid.
+
+ If the grid currently has N variants, adding a dimension with M variants
+ results in a grid containing N*M variants. Of course, we can't display
+ more than 2 dimensions on a 2D screen, so adding dimensions beyond 2
+ repeats all previous dimensions down vertically, with the grid width
+ set to the number of variants of the first dimension (unless overridden
+ by setting `grid_width`). For instance, a 3D variant space with
+ dimensions 3 x 2 x 2 will result in this layout:
+ 000 100 200
+ 010 110 210
+
+ 001 101 201
+ 011 111 211
+ """
+ new_variants = [
+ old_variant.merge_params(params or {}).with_grid_variant_name(name)
+ for name, params in variants.items()
+ for old_variant in self.variants
+ ]
+ # The first dimension dictates the grid-width, unless it was specified
+ # beforehand via the test params.
+ new_grid_width = (self._grid_width
+ if self._grid_width > 1 else len(variants))
+ return _VariantGrid(variants=new_variants, grid_width=new_grid_width)
+
+ def merge_params(self, name: str, params: _TestParams) -> '_VariantGrid':
+ """Merges the specified `params` into every variant of this grid."""
+ return _VariantGrid(variants=[
+ variant.merge_params(params).with_file_variant_name(name)
+ for variant in self.variants
+ ],
+ grid_width=self._grid_width)
+
+ def _variants_for_canvas_type(
+ self, canvas_type: _CanvasType) -> List[_TestParams]:
+ """Returns the variants of this grid enabled for `canvas_type`."""
+ return [
+ v.params for v in self.variants
+ if canvas_type in v.params['canvas_types']
+ ]
+
+ def _unique_param(self, name: str) -> Any:
+ """Returns the value of the `name` param for this grid.
+
+ All the variants in this grid must agree on the same value for this
+ parameter, or else an exception is thrown."""
+ values = {variant.params.get(name) for variant in self.variants}
+ if len(values) != 1:
+ raise InvalidTestDefinitionError(
+ 'All variants in a variant grid must use the same value '
+ f'for property "{name}". Got these values: {values}. '
+ 'Consider specifying the property outside of grid '
+ 'variants dimensions (in the base test definition or in a '
+ 'file variant dimension)')
+ return values.pop()
+
+ def _param_set(self, name: str):
+ """Returns the set of all values this grid has for the `name` param.
+
+ The `name` parameter of each variant is expected to be a sequence.
+ These are all accumulated in a set and returned."""
+ return frozenset(sum([list(v.params[name]) for v in self.variants],
+ []))
+
+ def _get_grid_params(self) -> _TestParams:
+ """Returns the params dict needed to render this grid with Jinja."""
+ filter_variant = self._variants_for_canvas_type
+ grid_params = {
+ 'element_variants': filter_variant(_CanvasType.HTML_CANVAS),
+ 'offscreen_variants': filter_variant(_CanvasType.OFFSCREEN_CANVAS),
+ 'worker_variants': filter_variant(_CanvasType.WORKER),
+ 'grid_width': self._grid_width,
+ 'name': self._unique_param('name'),
+ 'test_type': self._unique_param('test_type'),
+ 'fuzzy': self._unique_param('fuzzy'),
+ 'timeout': self._unique_param('timeout'),
+ 'notes': self._unique_param('notes'),
+ 'images': self._param_set('images'),
+ 'svgimages': self._param_set('svgimages'),
+ }
+ if self.template_type in (_TemplateType.REFERENCE,
+ _TemplateType.HTML_REFERENCE):
+ grid_params['desc'] = self._unique_param('desc')
+ return grid_params
+
def _write_reference_test(self, jinja_env: jinja2.Environment,
output_files: _OutputPaths):
+ grid = '_grid' if len(self.variants) > 1 else ''
+
+ # If variants don't all use the same offscreen and worker canvas types,
+ # the offscreen and worker grids won't be identical. The worker test
+ # therefore can't reuse the offscreen reference file.
+ offscreen_types = {_CanvasType.OFFSCREEN_CANVAS, _CanvasType.WORKER}
+ needs_worker_reference = len({
+ variant.params['canvas_types'] & offscreen_types
+ for variant in self.variants
+ }) != 1
+
params = dict(self.params)
- if _CanvasType.HTML_CANVAS in params['canvas_types']:
- _render(jinja_env, 'reftest_element.html', params,
+ params['reference_file'] = f'{params["name"]}-expected.html'
+ if _CanvasType.HTML_CANVAS in self.canvas_types:
+ _render(jinja_env, f'reftest_element{grid}.html', params,
f'{output_files.element}.html')
- if _CanvasType.OFFSCREEN_CANVAS in params['canvas_types']:
- _render(jinja_env, 'reftest_offscreen.html', params,
+ if _CanvasType.OFFSCREEN_CANVAS in self.canvas_types:
+ _render(jinja_env, f'reftest_offscreen{grid}.html', params,
f'{output_files.offscreen}.html')
- if _CanvasType.WORKER in params['canvas_types']:
- _render(jinja_env, 'reftest_worker.html', params,
+ if _CanvasType.WORKER in self.canvas_types:
+ if needs_worker_reference:
+ params['reference_file'] = f'{params["name"]}.w-expected.html'
+ _render(jinja_env, f'reftest_worker{grid}.html', params,
f'{output_files.offscreen}.w.html')
params['is_test_reference'] = True
- is_html_ref = params['template_type'] == _TemplateType.HTML_REFERENCE
- ref_template = 'reftest.html' if is_html_ref else 'reftest_element.html'
- if _CanvasType.HTML_CANVAS in params['canvas_types']:
- _render(jinja_env, ref_template, params,
+ is_html_ref = self.template_type == _TemplateType.HTML_REFERENCE
+ ref_template_name = (f'reftest{grid}.html'
+ if is_html_ref else f'reftest_element{grid}.html')
+
+ if _CanvasType.HTML_CANVAS in self.canvas_types:
+ _render(jinja_env, ref_template_name, params,
f'{output_files.element}-expected.html')
- if {_CanvasType.OFFSCREEN_CANVAS, _CanvasType.WORKER
- } & params['canvas_types']:
- _render(jinja_env, ref_template, params,
+
+ if self.canvas_types & offscreen_types:
+ # We use the same template for all reference files, so we need to
+ # assign the variant definition to the variable expected by the
+ # template.
+ params['element_variants'] = params.get('offscreen_variants')
+ _render(jinja_env, ref_template_name, params,
f'{output_files.offscreen}-expected.html')
+ if needs_worker_reference:
+ params['element_variants'] = params.get('worker_variants')
+ _render(jinja_env, ref_template_name, params,
+ f'{output_files.offscreen}.w-expected.html')
def _write_testharness_test(self, jinja_env: jinja2.Environment,
output_files: _OutputPaths):
+ grid = '_grid' if len(self.variants) > 1 else ''
+
# Create test cases for canvas and offscreencanvas.
- if _CanvasType.HTML_CANVAS in self.params['canvas_types']:
- _render(jinja_env, 'testharness_element.html', self.params,
+ if _CanvasType.HTML_CANVAS in self.canvas_types:
+ _render(jinja_env, f'testharness_element{grid}.html', self.params,
f'{output_files.element}.html')
-
- if _CanvasType.OFFSCREEN_CANVAS in self.params['canvas_types']:
- _render(jinja_env, 'testharness_offscreen.html', self.params,
- f'{output_files.offscreen}.html')
-
- if _CanvasType.WORKER in self.params['canvas_types']:
- _render(jinja_env, 'testharness_worker.js', self.params,
+ if _CanvasType.OFFSCREEN_CANVAS in self.canvas_types:
+ _render(jinja_env, f'testharness_offscreen{grid}.html',
+ self.params, f'{output_files.offscreen}.html')
+ if _CanvasType.WORKER in self.canvas_types:
+ _render(jinja_env, f'testharness_worker{grid}.js', self.params,
f'{output_files.offscreen}.worker.js')
def generate_test(self, jinja_env: jinja2.Environment,
output_dirs: _OutputPaths) -> None:
"""Generate the test files to the specified output dirs."""
- output_files = output_dirs.sub_path(self.params['file_name'])
+ output_files = output_dirs.sub_path(self.file_name)
- if self.params['template_type'] in (_TemplateType.REFERENCE,
- _TemplateType.HTML_REFERENCE):
+ if self.template_type in (_TemplateType.REFERENCE,
+ _TemplateType.HTML_REFERENCE):
self._write_reference_test(jinja_env, output_files)
else:
self._write_testharness_test(jinja_env, output_files)
-def _recursive_expand_variant_matrix(original_test: _TestParams,
- variant_matrix: List[_TestParams],
- current_selection: List[Tuple[str, Any]],
- test_variants: List[_Variant]):
- if len(current_selection) == len(variant_matrix):
- # Selection for each variant is done, so add a new test to test_list.
- test = dict(original_test)
- variant_name_list = []
- for variant_name, variant_params in current_selection:
- test.update(variant_params)
- variant_name_list.append(variant_name)
- # Expose variant names as a list so they can be used from the yaml
- # files, which helps with better naming of tests.
- test.update({'variant_names': variant_name_list})
- test_variants.append(_Variant.create_with_defaults(test))
- else:
- # Continue the recursion with each possible selection for the current
- # variant.
- variant = variant_matrix[len(current_selection)]
- for variant_options in variant.items():
- current_selection.append(variant_options)
- _recursive_expand_variant_matrix(original_test, variant_matrix,
- current_selection, test_variants)
- current_selection.pop()
-
-
-def _get_variants(test: _TestParams) -> List[_Variant]:
- current_selection = []
- test_variants = []
- variants = test.get('variants', [])
+class _VariantLayout(str, enum.Enum):
+ SINGLE_FILE = 'single_file'
+ MULTI_FILES = 'multi_files'
+
+
+@dataclasses.dataclass
+class _VariantDimension:
+ variants: Mapping[str, _TestParams]
+ layout: _VariantLayout
+
+
+def _get_variant_dimensions(params: _TestParams) -> List[_VariantDimension]:
+ variants = params.get('variants', [])
if not isinstance(variants, list):
raise InvalidTestDefinitionError(
textwrap.dedent("""
Variants must be specified as a list of variant dimensions, e.g.:
- variants:
- - dimension1-variant1:
- param: ...
- dimension1-variant2:
- param: ...
- - dimension2-variant1:
- param: ...
- dimension2-variant2:
- param: ..."""))
- _recursive_expand_variant_matrix(test, variants, current_selection,
- test_variants)
- return test_variants
+ variants:
+ - dimension1-variant1:
+ param: ...
+ dimension1-variant2:
+ param: ...
+ - dimension2-variant1:
+ param: ...
+ dimension2-variant2:
+ param: ..."""))
+
+ variants_layout = params.get('variants_layout',
+ [_VariantLayout.MULTI_FILES] * len(variants))
+ if len(variants) != len(variants_layout):
+ raise InvalidTestDefinitionError(
+ 'variants and variants_layout must be lists of the same size')
+ invalid_layouts = [
+ l for l in variants_layout if l not in list(_VariantLayout)
+ ]
+ if invalid_layouts:
+ raise InvalidTestDefinitionError('Invalid variants_layout: ' +
+ ', '.join(invalid_layouts) +
+ '. Valid layouts are: ' +
+ ', '.join(_VariantLayout))
+
+ return [
+ _VariantDimension(z[0], z[1]) for z in zip(variants, variants_layout)
+ ]
+
+
+def _get_variant_grids(test: Mapping[str, Any]) -> List[_VariantGrid]:
+ base_variant = _Variant.create_with_defaults(test)
+ grid_width = base_variant.params.get('grid_width', 1)
+ grids = [_VariantGrid([base_variant], grid_width=grid_width)]
+ for dimension in _get_variant_dimensions(test):
+ variants = dimension.variants
+ if dimension.layout == _VariantLayout.MULTI_FILES:
+ grids = [
+ grid.merge_params(name, params)
+ for name, params in variants.items() for grid in grids
+ ]
+ else:
+ grids = [grid.add_dimension(variants) for grid in grids]
+ return grids
def _check_uniqueness(tested: DefaultDict[str, Set[_CanvasType]], name: str,
@@ -619,21 +827,30 @@ def generate_test_files(name_to_dir_file: str) -> None:
except FileExistsError:
pass # Ignore if it already exists,
- used_tests = collections.defaultdict(set)
+ used_filenames = collections.defaultdict(set)
+ used_variants = collections.defaultdict(set)
for test in tests:
print(test['name'])
- for variant in _get_variants(test):
- variant.finalize_params(jinja_env)
- if test['name'] != variant.params['name']:
- print(f' {variant.params["name"]}')
+ for grid in _get_variant_grids(test):
+
+ grid.finalize(jinja_env)
+ if test['name'] != grid.file_name:
+ print(f' {grid.file_name}')
- sub_dir = _get_test_sub_dir(variant.params['file_name'],
- name_to_sub_dir)
+ sub_dir = _get_test_sub_dir(grid.file_name, name_to_sub_dir)
output_sub_dirs = output_dirs.sub_path(sub_dir)
- _check_uniqueness(used_tests, variant.params['name'],
- variant.params['canvas_types'])
- variant.generate_expected_image(output_sub_dirs)
- variant.generate_test(jinja_env, output_sub_dirs)
+ _check_uniqueness(used_filenames, grid.file_name,
+ grid.canvas_types)
+ for variant in grid.variants:
+ _check_uniqueness(
+ used_variants,
+ '.'.join([grid.file_name] +
+ variant.params['grid_variant_names']),
+ grid.canvas_types)
+
+ for variant in grid.variants:
+ variant.generate_expected_image(output_sub_dirs)
+ grid.generate_test(jinja_env, output_sub_dirs)
print()
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_element.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_element.html
index 6f7a8c8507..8f403f84f2 100644
--- a/testing/web-platform/tests/html/canvas/tools/templates/reftest_element.html
+++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_element.html
@@ -3,7 +3,7 @@
{% if test_type == 'promise' %}<html class="reftest-wait">
{% endif %}
{% if not is_test_reference %}
-<link rel="match" href="{{ name }}-expected.html">
+<link rel="match" href="{{ reference_file }}">
{% if fuzzy %}<meta name=fuzzy content="{{ fuzzy }}">
{% endif %}
{% endif %}
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_element_grid.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_element_grid.html
new file mode 100644
index 0000000000..d1c90bd993
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_element_grid.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+{% if test_type == 'promise' %}<html class="reftest-wait">
+<script>pending_tests = {{ element_variants | length }};</script>
+{% endif %}
+{% if not is_test_reference %}
+<link rel="match" href="{{ reference_file }}">
+{% if fuzzy %}<meta name=fuzzy content="{{ fuzzy }}">
+{% endif %}
+{% endif %}
+{% if timeout %}<meta name="timeout" content="{{ timeout }}">
+{% endif %}
+<title>Canvas test: {{ name }}</title>
+<h1 style="font-size: 20px;">{{ name }}</h1>
+<p class="desc">{{ desc }}</p>
+{% if notes %}<p class="notes">{{ notes }}{% endif %}
+{% for image in images %}
+<img src="/images/{{ image }}" id="{{ image }}" class="resource">
+{% endfor -%}
+{% for svgimage in svgimages %}
+<svg><image xlink:href="/images/{{ svgimage }}" id="{{ svgimage
+ }}" class="resource"></svg>
+{% endfor %}
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat({{ grid_width }}, max-content);
+ font-size: 13px; text-align: center;">
+{% for variant in element_variants %}
+<span>
+ {% for variant_name in variant.grid_variant_names %}
+ <div>{{ variant_name }}</div>
+ {% endfor %}
+ <canvas id="canvas{{ variant.id
+ }}" width="{{ variant.size[0]
+ }}" height="{{ variant.size[1]
+ }}" style="outline: 1px solid"{{ variant.canvas }}>
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = document.getElementById("canvas{{ variant.id }}");
+ const ctx = canvas.getContext('2d'{%
+ if variant.attributes %}, {{ variant.attributes }}{% endif %});
+
+ {{ variant.reference | trim | indent(4) if is_test_reference else
+ variant.code_element | trim | indent(4) }}
+ {% if test_type == 'promise' %}
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove("reftest-wait");
+ }
+ {% endif %}
+ </script>
+</span>
+
+{% endfor %}
+</div>
+{% if test_type == 'promise' %}</html>{% endif %}
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_grid.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_grid.html
new file mode 100644
index 0000000000..9fd42b7aa5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_grid.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: {{ name }}</title>
+<h1 style="font-size: 20px;">{{ name }}</h1>
+<p class="desc">{{ desc }}</p>
+{% if notes %}<p class="notes">{{ notes }}{% endif %}
+{% for image in images %}
+<img src="/images/{{ image }}" id="{{ image }}" class="resource">
+{% endfor %}
+{% for svgimage in svgimages %}
+<svg><image xlink:href="/images/{{ svgimage
+ }}" id="{{ svgimage }}" class="resource"></svg>
+{% endfor %}
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat({{ grid_width }}, max-content);
+ font-size: 13px; text-align: center;">
+{% for variant in element_variants %}
+<span>
+ {% for variant_name in variant.grid_variant_names %}
+ <div>{{ variant_name }}</div>
+ {% endfor %}
+ <div style="width: {{ variant.size[0] }}px; height: {{ variant.size[1]
+ }}px; outline: 1px solid">
+ {{ variant.html_reference | trim | indent(4) }}
+ </div>
+</span>
+
+{% endfor %}
+</div>
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen.html
index abc840159f..2cd8e9750d 100644
--- a/testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen.html
+++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen.html
@@ -2,7 +2,7 @@
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
{% if test_type == 'promise' %}<html class="reftest-wait">
{% endif %}
-<link rel="match" href="{{ name }}-expected.html">
+<link rel="match" href="{{ reference_file }}">
{% if fuzzy %}<meta name=fuzzy content="{{ fuzzy }}">
{% endif %}
{% if timeout %}<meta name="timeout" content="{{ timeout }}">
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen_grid.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen_grid.html
new file mode 100644
index 0000000000..d001260bea
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_offscreen_grid.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+{% if test_type == 'promise' %}<html class="reftest-wait">
+<script>pending_tests = {{ offscreen_variants | length }};</script>
+{% endif %}
+<link rel="match" href="{{ reference_file }}">
+{% if fuzzy %}<meta name=fuzzy content="{{ fuzzy }}">
+{% endif %}
+{% if timeout %}<meta name="timeout" content="{{ timeout }}">
+{% endif %}
+<title>Canvas test: {{ name }}</title>
+<h1 style="font-size: 20px;">{{ name }}</h1>
+<p class="desc">{{ desc }}</p>
+{% if notes %}<p class="notes">{{ notes }}{% endif %}
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat({{ grid_width }}, max-content);
+ font-size: 13px; text-align: center;">
+{% for variant in offscreen_variants %}
+<span>
+ {% for variant_name in variant.grid_variant_names %}
+ <div>{{ variant_name }}</div>
+ {% endfor %}
+ <canvas id="canvas{{ variant.id
+ }}" width="{{ variant.size[0]
+ }}" height="{{ variant.size[1]
+ }}" style="outline: 1px solid"{{ variant.canvas }}>
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script type="module">
+ const canvas = new OffscreenCanvas({{ variant.size[0] }}, {{
+ variant.size[1] }});
+ const ctx = canvas.getContext('2d'{%
+ if variant.attributes %}, {{ variant.attributes }}{% endif %});
+
+ {{ variant.code_offscreen | trim | indent(4) }}
+
+ const outputCanvas = document.getElementById("canvas{{ variant.id }}");
+ const outputCtx = outputCanvas.getContext('2d'{%
+ if variant.attributes %}, {{ variant.attributes }}{% endif %});
+ outputCtx.drawImage(canvas, 0, 0);
+{% if test_type == 'promise' %}
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove("reftest-wait");
+ }
+{% endif %}
+ </script>
+</span>
+
+{% endfor %}
+</div>
+{% if test_type == 'promise' %}</html>{% endif %}
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_worker.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_worker.html
index 02281af5d1..50aa29d00d 100644
--- a/testing/web-platform/tests/html/canvas/tools/templates/reftest_worker.html
+++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_worker.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
-<link rel="match" href="{{ name }}-expected.html">
+<link rel="match" href="{{ reference_file }}">
{% if fuzzy %}<meta name=fuzzy content="{{ fuzzy }}">
{% endif %}
{% if timeout %}<meta name="timeout" content="{{ timeout }}">
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_worker_grid.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_worker_grid.html
new file mode 100644
index 0000000000..652dddffd8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_worker_grid.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="{{ reference_file }}">
+{% if fuzzy %}<meta name=fuzzy content="{{ fuzzy }}">
+{% endif %}
+{% if timeout %}<meta name="timeout" content="{{ timeout }}">
+{% endif %}
+<title>Canvas test: {{ name }}</title>
+<h1 style="font-size: 20px;">{{ name }}</h1>
+<p class="desc">{{ desc }}</p>
+{% if notes %}<p class="notes">{{ notes }}{% endif %}
+<script>pending_tests = {{ worker_variants | length }};</script>
+
+<div style="display: grid; grid-gap: 4px;
+ grid-template-columns: repeat({{ grid_width }}, max-content);
+ font-size: 13px; text-align: center;">
+{% for variant in worker_variants %}
+<span>
+ {% for variant_name in variant.grid_variant_names %}
+ <div>{{ variant_name }}</div>
+ {% endfor %}
+ <canvas id="canvas{{ variant.id
+ }}" width="{{ variant.size[0]
+ }}" height="{{ variant.size[1]
+ }}" style="outline: 1px solid"{{ variant.canvas }}>
+ <p class="fallback">FAIL (fallback content)</p>
+ </canvas>
+ <script id="myWorker{{ variant.id }}" type="text/worker">
+ {% set async = 'async ' if test_type == 'promise' else '' %}
+ self.onmessage = {{async}}function(e) {
+ const canvas = new OffscreenCanvas({{
+ variant.size[0] }}, {{ variant.size[1] }});
+ const ctx = canvas.getContext('2d'{%
+ if variant.attributes %}, {{ variant.attributes }}{% endif %});
+
+ {{ variant.code_worker | trim | indent(6) }}
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+ </script>
+ <script type="module">
+ const blob = new Blob([document.getElementById('myWorker{{
+ variant.id }}').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCanvas = document.getElementById('canvas{{ variant.id }}');
+ const outputCtx = outputCanvas.getContext('2d'{%
+ if variant.attributes %}, {{ variant.attributes }}{% endif %});
+ outputCtx.drawImage(msg.data, 0, 0);
+ if (--pending_tests == 0) {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ });
+ worker.postMessage(null);
+ </script>
+</span>
+
+{% endfor %}
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/testharness_element_grid.html b/testing/web-platform/tests/html/canvas/tools/templates/testharness_element_grid.html
new file mode 100644
index 0000000000..b8f0ffe020
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/templates/testharness_element_grid.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: {{ name }}</title>
+{% if timeout %}<meta name="timeout" content="{{ timeout }}">{% endif %}
+<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">
+
+{% if fonts %}
+<style>
+{% for font in fonts %}
+ @font-face {
+ font-family: {{ font }};
+ src: url("/fonts/{{ font }}.ttf");
+ }
+{% endfor %}
+</style>
+{% if not font_unused_in_dom %}
+{% for font in fonts %}
+<span style="font-family: {{ font }};
+ position: absolute; visibility: hidden">A</span>
+{% endfor %}
+{% endif %}
+{% endif %}
+{% for image in images %}
+<img src="/images/{{ image }}" id="{{ image }}" class="resource">
+{% endfor %}
+{% for svgimage in svgimages %}
+<svg><image xlink:href="/images/{{ svgimage }}" id="{{ svgimage
+ }}" class="resource"></svg>
+{% endfor %}
+<script>
+{% for variant in element_variants %}
+
+{% if test_type == 'promise' %}
+promise_test(async t => {
+{% elif test_type == 'async' %}
+async_test(t => {
+{% else %}
+test(t => {
+{% endif %}
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d'{%
+ if attributes %}, {{ variant.attributes }}{% endif %});
+
+ {{ variant.code_element | trim | indent(2) }}
+}, "{{ variant.desc | double_quote_escape }}");
+{% endfor %}
+
+</script>
+</div>
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/testharness_offscreen_grid.html b/testing/web-platform/tests/html/canvas/tools/templates/testharness_offscreen_grid.html
new file mode 100644
index 0000000000..6e5628036b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/templates/testharness_offscreen_grid.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: {{ name }}</title>
+{% if timeout %}<meta name="timeout" content="{{ timeout }}">{% endif %}
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<script>
+{% for variant in offscreen_variants %}
+
+{% if test_type == 'promise' %}
+promise_test(async t => {
+{% elif test_type == 'async' %}
+async_test(t => {
+{% else %}
+test(t => {
+{% endif %}
+ const canvas = new OffscreenCanvas({{
+ variant.size[0] }}, {{ variant.size[1] }});
+ const ctx = canvas.getContext('2d'{%
+ if variant.attributes %}, {{ variant.attributes }}{% endif %});
+
+ {{ variant.code_offscreen | trim | indent(2)}}
+}, "{{ variant.desc | double_quote_escape }}");
+{% endfor %}
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/tools/templates/testharness_worker_grid.js b/testing/web-platform/tests/html/canvas/tools/templates/testharness_worker_grid.js
new file mode 100644
index 0000000000..53c3b69cb6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/templates/testharness_worker_grid.js
@@ -0,0 +1,27 @@
+{% if timeout %}// META: timeout={{ timeout }}{% endif %}
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:{{ name }}
+// Description:{{ desc }}
+// Note:{% if notes %}<p class="notes">{{ notes }}{% endif +%}
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+{% for variant in worker_variants %}
+
+{% if test_type == 'promise' %}
+promise_test(async t => {
+{% elif test_type == 'async' %}
+async_test(t => {
+{% else %}
+test(t => {
+{% endif %}
+ const canvas = new OffscreenCanvas({{
+ variant.size[0] }}, {{ variant.size[1] }});
+ const ctx = canvas.getContext('2d'{%
+ if variant.attributes %}, {{ variant.attributes }}{% endif %});
+
+ {{ variant.code_worker | trim | indent(2)}}
+}, "{{ variant.desc | double_quote_escape }}");
+{% endfor %}
+
+done();
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
index 1ce9d8ed74..9a738a37bd 100644
--- a/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
@@ -617,8 +617,7 @@
tentative: .tentative
- name: >-
- 2d.filter.{{ variant_names[0] }}.gaussianBlur.{{ variant_names[1] }}{{
- tentative }}
+ 2d.filter.{{ variant_names[0] }}.gaussianBlur{{ tentative }}
desc: Test CanvasFilter() with gaussianBlur.
size: [100, 100]
code: |
@@ -633,13 +632,14 @@
<svg xmlns="http://www.w3.org/2000/svg"
width="{{ size[0] }}" height="{{ size[1] }}"
color-interpolation-filters="sRGB">
- <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <filter id="blur{{ id }}" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="{{ blur_x }} {{blur_y}}" />
</filter>
<rect x="25" y="25" width="50" height="50"
- fill="teal" filter="url(#blur)" />
+ fill="teal" filter="url(#blur{{ id }})" />
</svg>
append_variants_to_name: false
+ variants_layout: [multi_files, single_file]
variants:
- layers:
filter_declaration: |-
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml
index d1e9a97043..e71155650b 100644
--- a/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml
@@ -1,14 +1,15 @@
- name: 2d.layer.global-states
desc: Checks that layers correctly use global render states.
- size: [200, 200]
+ size: [90, 90]
code: |
- ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ {{ transform_statement }}
- var circle = new Path2D();
- circle.arc(90, 90, 45, 0, 2 * Math.PI);
- ctx.fill(circle);
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
- {{ render_states }}
+ {{ alpha_statement }}
+ {{ composite_op_statement }}
+ {{ shadow_statement }}
ctx.beginLayer();
@@ -16,118 +17,86 @@
// 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(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
ctx.fillStyle = 'rgba(0, 255, 0, 1)';
- ctx.fillRect(70, 70, 75, 50);
+ ctx.fillRect(30, 5, 50, 40);
ctx.endLayer();
reference: |
- ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ {{ transform_statement }}
- var circle = new Path2D();
- circle.arc(90, 90, 45, 0, 2 * Math.PI);
- ctx.fill(circle);
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
- {{ render_states }}
+ {{ alpha_statement }}
+ {{ composite_op_statement }}
+ {{ shadow_statement }}
- canvas2 = document.createElement("canvas");
- ctx2 = canvas2.getContext("2d");
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
ctx2.globalCompositeOperation = 'screen';
- ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
- ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 40, 50);
ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
- ctx2.fillRect(70, 70, 75, 50);
+ ctx2.fillRect(30, 5, 50, 40);
ctx.drawImage(canvas2, 0, 0);
- variants:
- - &global-state-variants
- no-global-states:
- render_states: // No global states.
- alpha: &global-state-alpha
- render_states: ctx.globalAlpha = 0.6;
+ variants_layout: [single_file, multi_files, multi_files, multi_files]
+ variants: &global-state-variants
+ - no-globalAlpha:
+ alpha_statement: // No globalAlpha.
+ globalAlpha:
+ alpha_statement: ctx.globalAlpha = 0.75;
+ - no-composite-op:
+ composite_op_statement: // No globalCompositeOperation.
blending:
- render_states: ctx.globalCompositeOperation = 'multiply';
+ composite_op_statement: ctx.globalCompositeOperation = 'multiply';
composite:
- render_states: ctx.globalCompositeOperation = 'source-in';
+ composite_op_statement: ctx.globalCompositeOperation = 'source-in';
+ copy:
+ composite_op_statement: ctx.globalCompositeOperation = 'copy';
+ - no-shadow:
+ shadow_statement: // No shadow.
shadow:
- render_states: |-
- ctx.shadowOffsetX = -10;
- ctx.shadowOffsetY = 10;
- ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
- ctx.shadowBlur = 3;
- alpha.blending: &global-state-alpha-blending
- render_states: |-
- ctx.globalAlpha = 0.6;
- ctx.globalCompositeOperation = 'multiply';
- alpha.composite: &global-state-alpha-composite
- render_states: |-
- ctx.globalAlpha = 0.6;
- ctx.globalCompositeOperation = 'source-in';
- alpha.shadow: &global-state-alpha-shadow
- render_states: |-
- ctx.globalAlpha = 0.5;
- ctx.shadowOffsetX = -10;
- ctx.shadowOffsetY = 10;
- ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
- ctx.shadowBlur = 3;
- alpha.blending.shadow:
- render_states: |-
- ctx.globalAlpha = 0.6;
- ctx.globalCompositeOperation = 'multiply';
- ctx.shadowOffsetX = -10;
- ctx.shadowOffsetY = 10;
- ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
- ctx.shadowBlur = 3;
- alpha.composite.shadow:
- render_states: |-
- 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;
- blending.shadow:
- render_states: |-
- ctx.globalCompositeOperation = 'multiply';
- ctx.shadowOffsetX = -10;
- ctx.shadowOffsetY = 10;
- ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
- ctx.shadowBlur = 3;
- composite.shadow:
- render_states: |-
- ctx.globalCompositeOperation = 'source-in';
- ctx.shadowOffsetX = -10;
- ctx.shadowOffsetY = 10;
+ shadow_statement: |-
+ ctx.shadowOffsetX = -7;
+ ctx.shadowOffsetY = 7;
ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
ctx.shadowBlur = 3;
+ - no-transform:
+ transform_statement: // No transform.
+ rotation:
+ transform_statement: |-
+ ctx.translate(50, 40);
+ ctx.rotate(Math.PI);
+ ctx.translate(-45, -45);
+
- name: 2d.layer.global-states.filter
desc: Checks that layers with filters correctly use global render states.
- size: [200, 200]
+ size: [90, 90]
code: |
- ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ {{ transform_statement }}
- var circle = new Path2D();
- circle.arc(90, 90, 45, 0, 2 * Math.PI);
- ctx.fill(circle);
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
- {{ render_states }}
+ {{ alpha_statement }}
+ {{ composite_op_statement }}
+ {{ shadow_statement }}
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: 'dropShadow',
+ dx: 5, dy: 5, stdDeviation: 0, floodColor: '#00f'},
{name: 'componentTransfer',
- funcA: {type: "table", tableValues: [0, 0.7]}},
- {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+ funcA: {type: "table", tableValues: [0, 0.8]}}]});
- 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.fillStyle = 'rgba(255, 0, 0, 1)';
+ ctx.fillRect(10, 25, 40, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(30, 5, 50, 40);
ctx.endLayer();
reference: |
@@ -136,20 +105,14 @@
width="{{ size[0] }}" height="{{ size[1] }}"
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" />
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="#00f" />
<feComponentTransfer>
- <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ <feFuncA type="table" tableValues="0 0.8"></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)"/>
+ <rect x="10" y="25" width="40" height="50" fill="rgba(255, 0, 0, 1)"/>
+ <rect x="30" y="5" width="50" height="40" fill="rgba(0, 255, 0, 1)"/>
</g>
</svg>`;
@@ -157,31 +120,100 @@
img.width = {{ size[0] }};
img.height = {{ size[1] }};
img.onload = () => {
- ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ {{ transform_statement | indent(2) }}
- var circle = new Path2D();
- circle.arc(90, 90, 45, 0, 2 * Math.PI);
- ctx.fill(circle);
+ ctx.fillStyle = 'rgba(128, 128, 128, 1)';
+ ctx.fillRect(20, 15, 50, 50);
- {{ render_states }}
+ {{ alpha_statement | indent(2) }}
+ {{ composite_op_statement | indent(2) }}
+ {{ shadow_statement | indent(2) }}
ctx.drawImage(img, 0, 0);
};
img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+ variants_layout: [single_file, multi_files, multi_files, multi_files]
+ variants: *global-state-variants
+
+- name: 2d.layer.globalCompositeOperation
+ desc: Checks that layers work with all globalCompositeOperation values.
+ size: [90, 90]
+ code: |
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = '{{ variant_names[0] }}';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx.fillRect(10, 25, 25, 20);
+ ctx.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx.fillRect(25, 10, 20, 25);
+
+ ctx.endLayer();
+ reference: |
+ ctx.translate(50, 50);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI);
+ ctx.translate(-25, -25);
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.8)';
+ ctx.fillRect(15, 15, 25, 25);
+
+ ctx.globalAlpha = 0.75;
+ ctx.globalCompositeOperation = '{{ variant_names[0] }}';
+ ctx.shadowOffsetX = 7;
+ ctx.shadowOffsetY = 7;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ const canvas2 = document.createElement("canvas");
+ const ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(204, 0, 0, 1)';
+ ctx2.fillRect(10, 25, 25, 20);
+ ctx2.fillStyle = 'rgba(0, 204, 0, 1)';
+ ctx2.fillRect(25, 10, 20, 25);
+
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(canvas2, 0, 0);
+ variants_layout: [single_file]
+ grid_width: 7
variants:
- - <<: *global-state-variants
- alpha:
- <<: *global-state-alpha
- fuzzy: maxDifference=0-2; totalPixels=0-6766
- alpha.blending:
- <<: *global-state-alpha-blending
- fuzzy: maxDifference=0-1; totalPixels=0-2453
- alpha.composite:
- <<: *global-state-alpha-composite
- fuzzy: maxDifference=0-1; totalPixels=0-5204
- alpha.shadow:
- <<: *global-state-alpha-shadow
- fuzzy: maxDifference=0-2; totalPixels=0-6311
+ - source-over:
+ source-in:
+ source-atop:
+ destination-over:
+ destination-in:
+ destination-out:
+ destination-atop:
+ lighter:
+ copy:
+ xor:
+ multiply:
+ screen:
+ overlay:
+ darken:
+ lighten:
+ color-dodge:
+ color-burn:
+ hard-light:
+ soft-light:
+ difference:
+ exclusion:
+ hue:
+ saturation:
+ color:
+ luminosity:
- name: 2d.layer.global-filter
desc: Tests that layers ignore the global context filter.
@@ -428,6 +460,7 @@
- name: 2d.layer.ctm.getTransform
desc: Tests getTransform inside layers.
+ test_type: sync
code: |
ctx.translate(10, 20);
ctx.beginLayer();
@@ -559,7 +592,7 @@
desc: Check that layers state stack is flushed and rebuilt on frame renders.
size: [200, 200]
canvas_types: ['HtmlCanvas']
- test_type: "promise"
+ test_type: promise
code: |
ctx.fillStyle = 'purple';
ctx.fillRect(60, 60, 75, 50);
@@ -599,10 +632,9 @@
ctx.fillRect(80, 40, 75, 50);
- name: 2d.layer.malformed-operations
- desc: >-
- Check that exceptions are thrown for operations that are malformed while
- layers are open.
+ desc: Throws if {{ variant_names[0] }} is called while layers are open.
size: [200, 200]
+ test_type: sync
code: |
{{ setup }}
// Shouldn't throw on its own.
@@ -613,6 +645,7 @@
ctx.beginLayer();
assert_throws_dom("InvalidStateError",
() => {{ operation }});
+ variants_layout: [single_file]
variants:
- createPattern:
operation: ctx.createPattern(canvas, 'repeat')
@@ -639,11 +672,9 @@
operation: canvas.transferToImageBitmap()
- name: 2d.layer.malformed-operations-with-promises
- desc: >-
- Check that exceptions are thrown for operations that are malformed while
- layers are open.
+ desc: Throws if {{ variant_names[0] }} is called while layers are open.
size: [200, 200]
- test_type: "promise"
+ test_type: promise
code: |
// Shouldn't throw on its own.
await {{ operation }};
@@ -651,7 +682,9 @@
await {{ operation }};
// Calling again inside a layer should throw.
ctx.beginLayer();
- await promise_rejects_dom(t, 'InvalidStateError', {{ operation }});
+ await promise_rejects_dom(t, 'InvalidStateError',
+ {{ operation }});
+ variants_layout: [single_file]
variants:
- convertToBlob:
canvas_types: ['OffscreenCanvas', 'Worker']
@@ -864,6 +897,7 @@
- name: 2d.layer.invalid-calls
desc: Raises exception on {{ variant_desc }}.
+ test_type: sync
code: |
assert_throws_dom("INVALID_STATE_ERR", function() {
{{ call_sequence | indent(2) }}
@@ -903,6 +937,7 @@
- name: 2d.layer.exceptions-are-no-op
desc: Checks that the context state is left unchanged if beginLayer throws.
+ test_type: sync
code: |
// Get `beginLayer` to throw while parsing the filter.
assert_throws_js(TypeError,
@@ -927,6 +962,7 @@
- name: 2d.layer.beginLayer-options
desc: Checks beginLayer works for different option parameter values
+ test_type: sync
code: |
ctx.beginLayer(); ctx.endLayer();
ctx.beginLayer(null); ctx.endLayer();
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml/element/meta.yaml b/testing/web-platform/tests/html/canvas/tools/yaml/element/meta.yaml
index 5fd8b68498..12852e200a 100644
--- a/testing/web-platform/tests/html/canvas/tools/yaml/element/meta.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/yaml/element/meta.yaml
@@ -390,18 +390,12 @@
('hsl-4', 'hsl(-360240, 100%, 50%)', 0,255,0,255, ""),
('hsl-5', 'hsl(120.0, 100.0%, 50.0%)', 0,255,0,255, ""),
('hsl-6', 'hsl(+120, +100%, +50%)', 0,255,0,255, ""),
- ('hsl-clamp-1', 'hsl(120, 200%, 50%)', 0,255,0,255, ""),
- ('hsl-clamp-2', 'hsl(120, -200%, 49.9%)', 127,127,127,255, ""),
- ('hsl-clamp-3', 'hsl(120, 100%, 200%)', 255,255,255,255, ""),
- ('hsl-clamp-4', 'hsl(120, 100%, -200%)', 0,0,0,255, ""),
+ ('hsl-clamp-negative-saturation', 'hsl(120, -200%, 49.9%)', 127,127,127,255, ""),
('hsla-1', 'hsla(120, 100%, 50%, 0.499)', 0,255,0,127, ""),
('hsla-2', 'hsla( 120.0 , 100.0% , 50.0% , 1 )', 0,255,0,255, ""),
- ('hsla-clamp-1', 'hsla(120, 200%, 50%, 1)', 0,255,0,255, ""),
- ('hsla-clamp-2', 'hsla(120, -200%, 49.9%, 1)', 127,127,127,255, ""),
- ('hsla-clamp-3', 'hsla(120, 100%, 200%, 1)', 255,255,255,255, ""),
- ('hsla-clamp-4', 'hsla(120, 100%, -200%, 1)', 0,0,0,255, ""),
- ('hsla-clamp-5', 'hsla(120, 100%, 50%, 2)', 0,255,0,255, ""),
- ('hsla-clamp-6', 'hsla(120, 100%, 0%, -2)', 0,0,0,0, ""),
+ ('hsla-clamp-negative-saturation', 'hsla(120, -200%, 49.9%, 1)', 127,127,127,255, ""),
+ ('hsla-clamp-alpha-1', 'hsla(120, 100%, 50%, 2)', 0,255,0,255, ""),
+ ('hsla-clamp-alpha-2', 'hsla(120, 100%, 0%, -2)', 0,0,0,0, ""),
('svg-1', 'gray', 128,128,128,255, ""),
('svg-2', 'grey', 128,128,128,255, ""),
# css-color-4 rgb() color function
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml/offscreen/meta.yaml b/testing/web-platform/tests/html/canvas/tools/yaml/offscreen/meta.yaml
index 7b44fd9f26..b07898224d 100644
--- a/testing/web-platform/tests/html/canvas/tools/yaml/offscreen/meta.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/yaml/offscreen/meta.yaml
@@ -346,18 +346,12 @@
('hsl-4', 'hsl(-360240, 100%, 50%)', 0,255,0,255, ""),
('hsl-5', 'hsl(120.0, 100.0%, 50.0%)', 0,255,0,255, ""),
('hsl-6', 'hsl(+120, +100%, +50%)', 0,255,0,255, ""),
- ('hsl-clamp-1', 'hsl(120, 200%, 50%)', 0,255,0,255, ""),
- ('hsl-clamp-2', 'hsl(120, -200%, 49.9%)', 127,127,127,255, ""),
- ('hsl-clamp-3', 'hsl(120, 100%, 200%)', 255,255,255,255, ""),
- ('hsl-clamp-4', 'hsl(120, 100%, -200%)', 0,0,0,255, ""),
+ ('hsl-clamp-negative-saturation', 'hsl(120, -200%, 49.9%)', 127,127,127,255, ""),
('hsla-1', 'hsla(120, 100%, 50%, 0.499)', 0,255,0,127, ""),
('hsla-2', 'hsla( 120.0 , 100.0% , 50.0% , 1 )', 0,255,0,255, ""),
- ('hsla-clamp-1', 'hsla(120, 200%, 50%, 1)', 0,255,0,255, ""),
- ('hsla-clamp-2', 'hsla(120, -200%, 49.9%, 1)', 127,127,127,255, ""),
- ('hsla-clamp-3', 'hsla(120, 100%, 200%, 1)', 255,255,255,255, ""),
- ('hsla-clamp-4', 'hsla(120, 100%, -200%, 1)', 0,0,0,255, ""),
- ('hsla-clamp-5', 'hsla(120, 100%, 50%, 2)', 0,255,0,255, ""),
- ('hsla-clamp-6', 'hsla(120, 100%, 0%, -2)', 0,0,0,0, ""),
+ ('hsla-clamp-negative-saturation', 'hsla(120, -200%, 49.9%, 1)', 127,127,127,255, ""),
+ ('hsla-clamp-alpha-1', 'hsla(120, 100%, 50%, 2)', 0,255,0,255, ""),
+ ('hsla-clamp-alpha-2', 'hsla(120, 100%, 0%, -2)', 0,0,0,0, ""),
('svg-1', 'gray', 128,128,128,255, ""),
('svg-2', 'grey', 128,128,128,255, ""),
# css-color-4 rgb() color function