summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/canvas/offscreen/layers
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/canvas/offscreen/layers')
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.worker.js46
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html36
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping.w.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping-expected.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping.html33
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping.w.html47
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full.html26
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full.w.html40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial.html25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial.w.html39
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside.html30
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside.w.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-expected.html26
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside.html26
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside.w.html40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside-expected.html26
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside.html25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside.w.html39
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths-expected.html14
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow-expected.html17
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.html23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.w.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html32
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.worker.js27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter-expected.html17
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter.html29
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter.w.html43
-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.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.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.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.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.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.html41
-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.html55
-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.html41
-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.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html40
-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.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html58
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html54
-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.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.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.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.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.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-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.invalid-calls.beginLayer-reset-endLayer.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.worker.js26
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.html30
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.worker.js25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.worker.js26
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.html29
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.worker.js24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.worker.js26
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.html30
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.worker.js25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.html57
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.worker.js52
-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.js23
-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.js23
-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.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.nested-expected.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters-expected.html28
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters.html36
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters.w.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested.html39
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested.w.html53
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas.html36
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas.w.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset-expected.html14
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset.w.html52
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style-expected.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style.html28
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style.w.html42
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex.w.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-expected.html19
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html33
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.w.html47
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance.w.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-expected.html19
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html33
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.w.html47
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance.w.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-endLayer.html28
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-endLayer.worker.js23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.html28
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.worker.js23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.worker.js22
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.worker.js22
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.html28
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.worker.js23
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.worker.js22
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.html29
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.worker.js24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.html28
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.worker.js23
201 files changed, 7280 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic-expected.html
new file mode 100644
index 0000000000..6a6f0f6892
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.isotropic</title>
+<h1>2d.layer.anisotropic-blur.isotropic</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.html
new file mode 100644
index 0000000000..d59a4ccf62
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.isotropic-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.isotropic</title>
+<h1>2d.layer.anisotropic-blur.isotropic</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.isotropic.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.w.html
new file mode 100644
index 0000000000..15961d5c7e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.w.html
@@ -0,0 +1,37 @@
+<!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.anisotropic-blur.isotropic-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.isotropic</title>
+<h1>2d.layer.anisotropic-blur.isotropic</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x-expected.html
new file mode 100644
index 0000000000..b0473f2ff0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-x</title>
+<h1>2d.layer.anisotropic-blur.mostly-x</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.html
new file mode 100644
index 0000000000..c5ad2ee6c5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.mostly-x-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-x</title>
+<h1>2d.layer.anisotropic-blur.mostly-x</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 1] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.mostly-x.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.w.html
new file mode 100644
index 0000000000..60f5ac3ebd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.w.html
@@ -0,0 +1,37 @@
+<!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.anisotropic-blur.mostly-x-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-x</title>
+<h1>2d.layer.anisotropic-blur.mostly-x</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 1] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y-expected.html
new file mode 100644
index 0000000000..43da016eea
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-y</title>
+<h1>2d.layer.anisotropic-blur.mostly-y</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.html
new file mode 100644
index 0000000000..9545257cfa
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.mostly-y-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-y</title>
+<h1>2d.layer.anisotropic-blur.mostly-y</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [1, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.mostly-y.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.w.html
new file mode 100644
index 0000000000..d533ad3187
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.w.html
@@ -0,0 +1,37 @@
+<!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.anisotropic-blur.mostly-y-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-y</title>
+<h1>2d.layer.anisotropic-blur.mostly-y</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [1, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.x-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only-expected.html
new file mode 100644
index 0000000000..0b4d269189
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.x-only</title>
+<h1>2d.layer.anisotropic-blur.x-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.html
new file mode 100644
index 0000000000..4552ad4433
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.x-only-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.x-only</title>
+<h1>2d.layer.anisotropic-blur.x-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 0] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.x-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.w.html
new file mode 100644
index 0000000000..38abb21cd9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.w.html
@@ -0,0 +1,37 @@
+<!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.anisotropic-blur.x-only-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.x-only</title>
+<h1>2d.layer.anisotropic-blur.x-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 0] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.y-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only-expected.html
new file mode 100644
index 0000000000..2572386412
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.y-only</title>
+<h1>2d.layer.anisotropic-blur.y-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.html
new file mode 100644
index 0000000000..87dbcd3708
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.y-only-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.y-only</title>
+<h1>2d.layer.anisotropic-blur.y-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [0, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.anisotropic-blur.y-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.w.html
new file mode 100644
index 0000000000..062328db75
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.w.html
@@ -0,0 +1,37 @@
+<!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.anisotropic-blur.y-only-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.y-only</title>
+<h1>2d.layer.anisotropic-blur.y-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [0, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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
new file mode 100644
index 0000000000..4fb042a1d8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.beginLayer-options</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.beginLayer-options</h1>
+<p class="desc">Checks beginLayer works for different option parameter values</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.beginLayer(); ctx.endLayer();
+ ctx.beginLayer(null); ctx.endLayer();
+ ctx.beginLayer(undefined); ctx.endLayer();
+ ctx.beginLayer([]); ctx.endLayer();
+ ctx.beginLayer({}); ctx.endLayer();
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer(''); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(0); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(1); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(true); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(false); });
+
+ ctx.beginLayer({filter: null}); ctx.endLayer();
+ ctx.beginLayer({filter: undefined}); ctx.endLayer();
+ ctx.beginLayer({filter: []}); ctx.endLayer();
+ ctx.beginLayer({filter: {}}); ctx.endLayer();
+ ctx.beginLayer({filter: {name: "unknown"}}); ctx.endLayer();
+ ctx.beginLayer({filter: ''}); ctx.endLayer();
+
+ // These cases don't throw TypeError since they can be casted to a
+ // DOMString.
+ ctx.beginLayer({filter: 0}); ctx.endLayer();
+ ctx.beginLayer({filter: 1}); ctx.endLayer();
+ ctx.beginLayer({filter: true}); ctx.endLayer();
+ ctx.beginLayer({filter: false}); ctx.endLayer();
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..cafbc83f3e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.beginLayer-options.worker.js
@@ -0,0 +1,46 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.beginLayer-options
+// Description:Checks beginLayer works for different option parameter values
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ ctx.beginLayer(); ctx.endLayer();
+ ctx.beginLayer(null); ctx.endLayer();
+ ctx.beginLayer(undefined); ctx.endLayer();
+ ctx.beginLayer([]); ctx.endLayer();
+ ctx.beginLayer({}); ctx.endLayer();
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer(''); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(0); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(1); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(true); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(false); });
+
+ ctx.beginLayer({filter: null}); ctx.endLayer();
+ ctx.beginLayer({filter: undefined}); ctx.endLayer();
+ ctx.beginLayer({filter: []}); ctx.endLayer();
+ ctx.beginLayer({filter: {}}); ctx.endLayer();
+ ctx.beginLayer({filter: {name: "unknown"}}); ctx.endLayer();
+ ctx.beginLayer({filter: ''}); ctx.endLayer();
+
+ // These cases don't throw TypeError since they can be casted to a
+ // DOMString.
+ ctx.beginLayer({filter: 0}); ctx.endLayer();
+ ctx.beginLayer({filter: 1}); ctx.endLayer();
+ ctx.beginLayer({filter: true}); ctx.endLayer();
+ ctx.beginLayer({filter: false}); ctx.endLayer();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html
new file mode 100644
index 0000000000..6cad180f14
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.no-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.no-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur in="SourceGraphic" stdDeviation="30" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="201" y="50" width="100" height="100" fill="turquoise"/>
+ <rect x="50" y="201" width="100" height="100" fill="indigo"/>
+ <rect x="-101" y="50" width="100" height="100" fill="orange"/>
+ <rect x="50" y="-101" width="100" height="100" fill="brown"/>
+ </g>
+ </svg>`;
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ // No clipping.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping.html
new file mode 100644
index 0000000000..3cd1c674a1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.blur-from-outside-canvas.no-clipping-expected.html">
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.no-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.no-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [ {name: 'gaussianBlur', stdDeviation: 30} ]});
+
+ ctx.fillStyle = 'turquoise';
+ ctx.fillRect(201, 50, 100, 100);
+ ctx.fillStyle = 'indigo';
+ ctx.fillRect(50, 201, 100, 100);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(-1, 50, -100, 100);
+ ctx.fillStyle = 'brown';
+ ctx.fillRect(50, -1, 100, -100);
+
+ ctx.endLayer();
+
+ 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.blur-from-outside-canvas.no-clipping.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping.w.html
new file mode 100644
index 0000000000..90b013c077
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.no-clipping.w.html
@@ -0,0 +1,45 @@
+<!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.blur-from-outside-canvas.no-clipping-expected.html">
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.no-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.no-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [ {name: 'gaussianBlur', stdDeviation: 30} ]});
+
+ ctx.fillStyle = 'turquoise';
+ ctx.fillRect(201, 50, 100, 100);
+ ctx.fillStyle = 'indigo';
+ ctx.fillRect(50, 201, 100, 100);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(-1, 50, -100, 100);
+ ctx.fillStyle = 'brown';
+ ctx.fillRect(50, -1, 100, -100);
+
+ ctx.endLayer();
+
+ 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.blur-from-outside-canvas.with-clipping-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping-expected.html
new file mode 100644
index 0000000000..1823f78983
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping-expected.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.with-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.with-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur in="SourceGraphic" stdDeviation="30" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="201" y="50" width="100" height="100" fill="turquoise"/>
+ <rect x="50" y="201" width="100" height="100" fill="indigo"/>
+ <rect x="-101" y="50" width="100" height="100" fill="orange"/>
+ <rect x="50" y="-101" width="100" height="100" fill="brown"/>
+ </g>
+ </svg>`;
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping.html
new file mode 100644
index 0000000000..76477445e5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.blur-from-outside-canvas.with-clipping-expected.html">
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.with-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.with-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [ {name: 'gaussianBlur', stdDeviation: 30} ]});
+
+ ctx.fillStyle = 'turquoise';
+ ctx.fillRect(201, 50, 100, 100);
+ ctx.fillStyle = 'indigo';
+ ctx.fillRect(50, 201, 100, 100);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(-1, 50, -100, 100);
+ ctx.fillStyle = 'brown';
+ ctx.fillRect(50, -1, 100, -100);
+
+ ctx.endLayer();
+
+ 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.blur-from-outside-canvas.with-clipping.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping.w.html
new file mode 100644
index 0000000000..cf5570c932
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.blur-from-outside-canvas.with-clipping.w.html
@@ -0,0 +1,47 @@
+<!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.blur-from-outside-canvas.with-clipping-expected.html">
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.with-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.with-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [ {name: 'gaussianBlur', stdDeviation: 30} ]});
+
+ ctx.fillStyle = 'turquoise';
+ ctx.fillRect(201, 50, 100, 100);
+ ctx.fillStyle = 'indigo';
+ ctx.fillRect(50, 201, 100, 100);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(-1, 50, -100, 100);
+ ctx.fillStyle = 'brown';
+ ctx.fillRect(50, -1, 100, -100);
+
+ ctx.endLayer();
+
+ 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.clearRect.full-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full-expected.html
new file mode 100644
index 0000000000..5a47f8e118
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clearRect.full</title>
+<h1>2d.layer.clearRect.full</h1>
+<p class="desc">clearRect inside a layer can clear all of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full.html
new file mode 100644
index 0000000000..ec9f453b69
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clearRect.full-expected.html">
+<title>Canvas test: 2d.layer.clearRect.full</title>
+<h1>2d.layer.clearRect.full</h1>
+<p class="desc">clearRect inside a layer can clear all of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 50);
+ ctx.fillStyle = 'green';
+ ctx.clearRect(0, 0, 100, 100);
+ ctx.endLayer();
+
+ 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.clearRect.full.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full.w.html
new file mode 100644
index 0000000000..a6f4021dd5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.full.w.html
@@ -0,0 +1,40 @@
+<!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.clearRect.full-expected.html">
+<title>Canvas test: 2d.layer.clearRect.full</title>
+<h1>2d.layer.clearRect.full</h1>
+<p class="desc">clearRect inside a layer can clear all of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 50);
+ ctx.fillStyle = 'green';
+ ctx.clearRect(0, 0, 100, 100);
+ ctx.endLayer();
+
+ 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.clearRect.partial-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial-expected.html
new file mode 100644
index 0000000000..ac75105cec
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clearRect.partial</title>
+<h1>2d.layer.clearRect.partial</h1>
+<p class="desc">clearRect inside a layer can clear a portion of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 10);
+ ctx.fillRect(20, 60, 80, 10);
+ ctx.fillRect(20, 20, 10, 50);
+ ctx.fillRect(90, 20, 10, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial.html
new file mode 100644
index 0000000000..88509a8a40
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clearRect.partial-expected.html">
+<title>Canvas test: 2d.layer.clearRect.partial</title>
+<h1>2d.layer.clearRect.partial</h1>
+<p class="desc">clearRect inside a layer can clear a portion of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 50);
+ ctx.clearRect(30, 30, 60, 30);
+ ctx.endLayer();
+
+ 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.clearRect.partial.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial.w.html
new file mode 100644
index 0000000000..c6ba41afd7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clearRect.partial.w.html
@@ -0,0 +1,39 @@
+<!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.clearRect.partial-expected.html">
+<title>Canvas test: 2d.layer.clearRect.partial</title>
+<h1>2d.layer.clearRect.partial</h1>
+<p class="desc">clearRect inside a layer can clear a portion of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 50);
+ ctx.clearRect(30, 30, 60, 30);
+ ctx.endLayer();
+
+ 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.clip-inside-and-outside-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside-expected.html
new file mode 100644
index 0000000000..14e6d56245
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clip-inside-and-outside</title>
+<h1>2d.layer.clip-inside-and-outside</h1>
+<p class="desc">Check clipping set inside and outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+
+ ctx2.beginPath();
+ ctx2.rect(15, 15, 70, 70);
+ ctx2.clip();
+
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(10, 10, 80, 80);
+
+ const canvas3 = new OffscreenCanvas(200, 200);
+ const ctx3 = canvas3.getContext('2d');
+
+ ctx3.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx3.drawImage(canvas2, 0, 0);
+ ctx3.endLayer();
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+ ctx.drawImage(canvas3, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside.html
new file mode 100644
index 0000000000..03a3aee605
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clip-inside-and-outside-expected.html">
+<title>Canvas test: 2d.layer.clip-inside-and-outside</title>
+<h1>2d.layer.clip-inside-and-outside</h1>
+<p class="desc">Check clipping set inside and outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+
+ 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.clip-inside-and-outside.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside.w.html
new file mode 100644
index 0000000000..71f9fe7db4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-and-outside.w.html
@@ -0,0 +1,44 @@
+<!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.clip-inside-and-outside-expected.html">
+<title>Canvas test: 2d.layer.clip-inside-and-outside</title>
+<h1>2d.layer.clip-inside-and-outside</h1>
+<p class="desc">Check clipping set inside and outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+
+ 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.clip-inside-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-expected.html
new file mode 100644
index 0000000000..281fc1d913
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside-expected.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clip-inside</title>
+<h1>2d.layer.clip-inside</h1>
+<p class="desc">Check clipping set inside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+
+ ctx2.beginPath();
+ ctx2.rect(15, 15, 70, 70);
+ ctx2.clip();
+
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(10, 10, 80, 80);
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx.drawImage(canvas2, 0, 0);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside.html
new file mode 100644
index 0000000000..e0c41f21e1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clip-inside-expected.html">
+<title>Canvas test: 2d.layer.clip-inside</title>
+<h1>2d.layer.clip-inside</h1>
+<p class="desc">Check clipping set inside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+
+ 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.clip-inside.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside.w.html
new file mode 100644
index 0000000000..9c4260a8ce
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-inside.w.html
@@ -0,0 +1,40 @@
+<!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.clip-inside-expected.html">
+<title>Canvas test: 2d.layer.clip-inside</title>
+<h1>2d.layer.clip-inside</h1>
+<p class="desc">Check clipping set inside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+
+ 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.clip-outside-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside-expected.html
new file mode 100644
index 0000000000..1b18c2e8a7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside-expected.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clip-outside</title>
+<h1>2d.layer.clip-outside</h1>
+<p class="desc">Check clipping set outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+
+ ctx2.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(10, 10, 80, 80);
+ ctx2.endLayer();
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside.html
new file mode 100644
index 0000000000..d2d091e96b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clip-outside-expected.html">
+<title>Canvas test: 2d.layer.clip-outside</title>
+<h1>2d.layer.clip-outside</h1>
+<p class="desc">Check clipping set outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+
+ 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.clip-outside.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside.w.html
new file mode 100644
index 0000000000..aed72db5ab
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.clip-outside.w.html
@@ -0,0 +1,39 @@
+<!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.clip-outside-expected.html">
+<title>Canvas test: 2d.layer.clip-outside</title>
+<h1>2d.layer.clip-outside</h1>
+<p class="desc">Check clipping set outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+
+ 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.cross-layer-paths-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths-expected.html
new file mode 100644
index 0000000000..c394ecdfe3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths-expected.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.cross-layer-paths</title>
+<h1>2d.layer.cross-layer-paths</h1>
+<p class="desc">Checks that path defined in a layer is usable outside.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.moveTo(50, 0); ctx.lineTo(50, 100); ctx.stroke();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths.html
new file mode 100644
index 0000000000..f167ae00bd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.cross-layer-paths-expected.html">
+<title>Canvas test: 2d.layer.cross-layer-paths</title>
+<h1>2d.layer.cross-layer-paths</h1>
+<p class="desc">Checks that path defined in a layer is usable outside.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer();
+ ctx.translate(50, 0);
+ ctx.moveTo(0, 0);
+ ctx.endLayer();
+ ctx.lineTo(50, 100);
+ ctx.stroke();
+
+ 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.cross-layer-paths.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths.w.html
new file mode 100644
index 0000000000..5b1f7f949c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.cross-layer-paths.w.html
@@ -0,0 +1,37 @@
+<!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.cross-layer-paths-expected.html">
+<title>Canvas test: 2d.layer.cross-layer-paths</title>
+<h1>2d.layer.cross-layer-paths</h1>
+<p class="desc">Checks that path defined in a layer is usable outside.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer();
+ ctx.translate(50, 0);
+ ctx.moveTo(0, 0);
+ ctx.endLayer();
+ ctx.lineTo(50, 100);
+ ctx.stroke();
+
+ 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.css-filters.blur-and-shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow-expected.html
new file mode 100644
index 0000000000..85503ae33a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow-expected.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.css-filters.blur-and-shadow</title>
+<h1>2d.layer.css-filters.blur-and-shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="5" />
+ <feDropShadow dx="10" dy="10" stdDeviation="5" flood-color="orange" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.html
new file mode 100644
index 0000000000..a44ce4707f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.css-filters.blur-and-shadow-expected.html">
+<title>Canvas test: 2d.layer.css-filters.blur-and-shadow</title>
+<h1>2d.layer.css-filters.blur-and-shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'blur(5px) drop-shadow(10px 10px 5px orange)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+
+ 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.css-filters.blur-and-shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.w.html
new file mode 100644
index 0000000000..9413ca6674
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.w.html
@@ -0,0 +1,37 @@
+<!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.css-filters.blur-and-shadow-expected.html">
+<title>Canvas test: 2d.layer.css-filters.blur-and-shadow</title>
+<h1>2d.layer.css-filters.blur-and-shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'blur(5px) drop-shadow(10px 10px 5px orange)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+
+ 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.css-filters.blur-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-expected.html
new file mode 100644
index 0000000000..c6131f6c1e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.css-filters.blur</title>
+<h1>2d.layer.css-filters.blur</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="10" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur.html
new file mode 100644
index 0000000000..5407ec37ad
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.css-filters.blur-expected.html">
+<title>Canvas test: 2d.layer.css-filters.blur</title>
+<h1>2d.layer.css-filters.blur</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'blur(10px)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.css-filters.blur.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur.w.html
new file mode 100644
index 0000000000..35af0e1bfb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.blur.w.html
@@ -0,0 +1,37 @@
+<!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.css-filters.blur-expected.html">
+<title>Canvas test: 2d.layer.css-filters.blur</title>
+<h1>2d.layer.css-filters.blur</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'blur(10px)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ 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.css-filters.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow-expected.html
new file mode 100644
index 0000000000..60f78d8096
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.css-filters.shadow</title>
+<h1>2d.layer.css-filters.shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="-10" dy="-10" stdDeviation="5" flood-color="purple" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.html
new file mode 100644
index 0000000000..28d6e6e403
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.css-filters.shadow-expected.html">
+<title>Canvas test: 2d.layer.css-filters.shadow</title>
+<h1>2d.layer.css-filters.shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'drop-shadow(-10px -10px 5px purple)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+
+ 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.css-filters.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.w.html
new file mode 100644
index 0000000000..98e9d2fbd4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.w.html
@@ -0,0 +1,37 @@
+<!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.css-filters.shadow-expected.html">
+<title>Canvas test: 2d.layer.css-filters.shadow</title>
+<h1>2d.layer.css-filters.shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'drop-shadow(-10px -10px 5px purple)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+
+ 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.exceptions-are-no-op.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html
new file mode 100644
index 0000000000..a047c539cf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.exceptions-are-no-op</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.exceptions-are-no-op</h1>
+<p class="desc">Checks that the context state is left unchanged if beginLayer throws.</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ // Get `beginLayer` to throw while parsing the filter.
+ assert_throws_js(TypeError,
+ () => ctx.beginLayer({filter: {name: 'colorMatrix',
+ values: 'foo'}}));
+ // `beginLayer` shouldn't have opened the layer, so `endLayer` should throw.
+ assert_throws_dom("InvalidStateError", () => ctx.endLayer());
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..bd1e376084
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.exceptions-are-no-op.worker.js
@@ -0,0 +1,27 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.exceptions-are-no-op
+// Description:Checks that the context state is left unchanged if beginLayer throws.
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ // Get `beginLayer` to throw while parsing the filter.
+ assert_throws_js(TypeError,
+ () => ctx.beginLayer({filter: {name: 'colorMatrix',
+ values: 'foo'}}));
+ // `beginLayer` shouldn't have opened the layer, so `endLayer` should throw.
+ assert_throws_dom("InvalidStateError", () => ctx.endLayer());
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter-expected.html
new file mode 100644
index 0000000000..88057fc354
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter-expected.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-filter</title>
+<h1>2d.layer.global-filter</h1>
+<p class="desc">Tests that layers ignore the global context filter.</p>
+<canvas id="canvas" width="150" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillRect(60, 10, 30, 30);
+ ctx.filter = 'blur(5px)'
+ ctx.fillRect(10, 10, 30, 30);
+ ctx.fillRect(110, 10, 30, 30);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter.html
new file mode 100644
index 0000000000..2388a06a96
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-filter-expected.html">
+<title>Canvas test: 2d.layer.global-filter</title>
+<h1>2d.layer.global-filter</h1>
+<p class="desc">Tests that layers ignore the global context filter.</p>
+<canvas id="canvas" width="150" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(150, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.filter = 'blur(5px)'
+
+ ctx.beginLayer();
+ ctx.fillRect(10, 10, 30, 30); // `ctx.filter` applied to draw call.
+ ctx.endLayer();
+
+ ctx.beginLayer();
+ ctx.filter = 'none';
+ ctx.fillRect(60, 10, 30, 30); // Should not be filted by the layer.
+ ctx.endLayer();
+
+ ctx.fillRect(110, 10, 30, 30); // `ctx.filter` is still set.
+
+ 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-filter.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter.w.html
new file mode 100644
index 0000000000..4c8f92d18a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-filter.w.html
@@ -0,0 +1,43 @@
+<!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-filter-expected.html">
+<title>Canvas test: 2d.layer.global-filter</title>
+<h1>2d.layer.global-filter</h1>
+<p class="desc">Tests that layers ignore the global context filter.</p>
+<canvas id="canvas" width="150" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(150, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.filter = 'blur(5px)'
+
+ ctx.beginLayer();
+ ctx.fillRect(10, 10, 30, 30); // `ctx.filter` applied to draw call.
+ ctx.endLayer();
+
+ ctx.beginLayer();
+ ctx.filter = 'none';
+ ctx.fillRect(60, 10, 30, 30); // Should not be filted by the layer.
+ ctx.endLayer();
+
+ ctx.fillRect(110, 10, 30, 30); // `ctx.filter` is still set.
+
+ 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-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha-expected.html
new file mode 100644
index 0000000000..0666e3098a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha</title>
+<h1>2d.layer.global-states.alpha</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..8a45027588
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.blending</title>
+<h1>2d.layer.global-states.alpha.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..71414b4b37
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..f7b633b35f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..ed2d2d70af
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..1ff3ad8385
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.shadow.w.html
@@ -0,0 +1,56 @@
+<!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
new file mode 100644
index 0000000000..618480c813
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.blending.w.html
@@ -0,0 +1,52 @@
+<!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
new file mode 100644
index 0000000000..951049e638
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.composite</title>
+<h1>2d.layer.global-states.alpha.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..94fed5752d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..0ae93871f5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..eb579cdcce
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..60e36f4b97
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.shadow.w.html
@@ -0,0 +1,56 @@
+<!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
new file mode 100644
index 0000000000..d7d2b7a21e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.composite.w.html
@@ -0,0 +1,52 @@
+<!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
new file mode 100644
index 0000000000..63a264e681
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..6f764c5001
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.shadow</title>
+<h1>2d.layer.global-states.alpha.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..65a66c977d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..f404601e3d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.shadow.w.html
@@ -0,0 +1,55 @@
+<!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
new file mode 100644
index 0000000000..694f31e208
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.alpha.w.html
@@ -0,0 +1,51 @@
+<!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
new file mode 100644
index 0000000000..33fdf46a28
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending</title>
+<h1>2d.layer.global-states.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.html
new file mode 100644
index 0000000000..6a36bb4ba1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow-expected.html
new file mode 100644
index 0000000000..6f969074f9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending.shadow</title>
+<h1>2d.layer.global-states.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..2e91f3d2d1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.w.html
new file mode 100644
index 0000000000..d8e20d0479
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.shadow.w.html
@@ -0,0 +1,55 @@
+<!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
new file mode 100644
index 0000000000..8964e97713
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.blending.w.html
@@ -0,0 +1,51 @@
+<!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
new file mode 100644
index 0000000000..ed7669c4cf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite</title>
+<h1>2d.layer.global-states.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.html
new file mode 100644
index 0000000000..84fb4b3d95
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow-expected.html
new file mode 100644
index 0000000000..b687c27f47
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite.shadow</title>
+<h1>2d.layer.global-states.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..1e3ab4d6a0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.w.html
new file mode 100644
index 0000000000..7dfb70148b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.shadow.w.html
@@ -0,0 +1,55 @@
+<!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
new file mode 100644
index 0000000000..b695871fcd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.composite.w.html
@@ -0,0 +1,51 @@
+<!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.filter.alpha-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha-expected.html
new file mode 100644
index 0000000000..f304700feb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
+<h1>2d.layer.global-states.filter.alpha</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..7c91ce4229
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
+<h1>2d.layer.global-states.filter.alpha.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..be6f962b33
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
+<h1>2d.layer.global-states.filter.alpha.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = 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
new file mode 100644
index 0000000000..62942ffeae
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..62d98d967c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
@@ -0,0 +1,45 @@
+<!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
new file mode 100644
index 0000000000..e81efd6b8d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.shadow.w.html
@@ -0,0 +1,59 @@
+<!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
new file mode 100644
index 0000000000..2b53ad7c1e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html
@@ -0,0 +1,55 @@
+<!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">
+<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
new file mode 100644
index 0000000000..8e0d98648e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
+<h1>2d.layer.global-states.filter.alpha.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..087fea88af
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
+<h1>2d.layer.global-states.filter.alpha.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = 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
new file mode 100644
index 0000000000..a649972546
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..d067ff2f5e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
@@ -0,0 +1,45 @@
+<!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
new file mode 100644
index 0000000000..39abc78b17
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.shadow.w.html
@@ -0,0 +1,59 @@
+<!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
new file mode 100644
index 0000000000..6aa83a3278
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html
@@ -0,0 +1,55 @@
+<!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">
+<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
new file mode 100644
index 0000000000..f1d631c25c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
+<h1>2d.layer.global-states.filter.alpha</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = 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
new file mode 100644
index 0000000000..169baee29b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..2548c21181
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = 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
new file mode 100644
index 0000000000..5e1494422e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html
@@ -0,0 +1,58 @@
+<!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">
+<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
new file mode 100644
index 0000000000..e75d668ad5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html
@@ -0,0 +1,54 @@
+<!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">
+<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
new file mode 100644
index 0000000000..f81dcf72dc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.blending</title>
+<h1>2d.layer.global-states.filter.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..ce2b046798
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.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.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow-expected.html
new file mode 100644
index 0000000000..91f3725f8e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow</title>
+<h1>2d.layer.global-states.filter.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..d0d429bee3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.html
@@ -0,0 +1,44 @@
+<!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.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.w.html
new file mode 100644
index 0000000000..ce432ea74d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.shadow.w.html
@@ -0,0 +1,58 @@
+<!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
new file mode 100644
index 0000000000..bb101cdc0b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.blending.w.html
@@ -0,0 +1,54 @@
+<!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
new file mode 100644
index 0000000000..97e85a1593
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.composite</title>
+<h1>2d.layer.global-states.filter.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..32052a1150
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.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.shadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow-expected.html
new file mode 100644
index 0000000000..4716bb2760
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow</title>
+<h1>2d.layer.global-states.filter.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..b5e8b9f843
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.html
@@ -0,0 +1,44 @@
+<!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.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.w.html
new file mode 100644
index 0000000000..894089d88e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.shadow.w.html
@@ -0,0 +1,58 @@
+<!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
new file mode 100644
index 0000000000..41ccdaf5c0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.composite.w.html
@@ -0,0 +1,54 @@
+<!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.no-global-states-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states-expected.html
new file mode 100644
index 0000000000..e56fe0b360
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.no-global-states</title>
+<h1>2d.layer.global-states.filter.no-global-states</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..3effa3ee9d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.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
new file mode 100644
index 0000000000..ec744d7ffe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.no-global-states.w.html
@@ -0,0 +1,54 @@
+<!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
new file mode 100644
index 0000000000..13ba2dd4cd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.shadow</title>
+<h1>2d.layer.global-states.filter.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..7bb0ef5e13
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.html
@@ -0,0 +1,43 @@
+<!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
new file mode 100644
index 0000000000..bc9bd48aad
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.shadow.w.html
@@ -0,0 +1,57 @@
+<!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-global-states-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states-expected.html
new file mode 100644
index 0000000000..b91a2ae8b5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-global-states</title>
+<h1>2d.layer.global-states.no-global-states</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/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
new file mode 100644
index 0000000000..c8a9815381
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..db03a3fd0c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.no-global-states.w.html
@@ -0,0 +1,51 @@
+<!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
new file mode 100644
index 0000000000..835e9d420a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.shadow</title>
+<h1>2d.layer.global-states.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.html
new file mode 100644
index 0000000000..ad60e87fb1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.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
new file mode 100644
index 0000000000..1fc35fd33a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.shadow.w.html
@@ -0,0 +1,54 @@
+<!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.invalid-calls.beginLayer-reset-endLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html
new file mode 100644
index 0000000000..c0b11aa611
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.invalid-calls.beginLayer-reset-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.invalid-calls.beginLayer-reset-endLayer</h1>
+<p class="desc">Raises exception on beginLayer() + reset() + endLayer().</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.reset();
+ ctx.endLayer();
+ });
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..1c147d6f34
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.worker.js
@@ -0,0 +1,26 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.invalid-calls.beginLayer-reset-endLayer
+// Description:Raises exception on beginLayer() + reset() + endLayer().
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.reset();
+ ctx.endLayer();
+ });
+ t.done();
+});
+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
new file mode 100644
index 0000000000..022532b329
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.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.layer.invalid-calls.beginLayer-restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.invalid-calls.beginLayer-restore</h1>
+<p class="desc">Raises exception on beginLayer() + restore().</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.restore();
+ });
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..1aa86635e6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-restore.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.layer.invalid-calls.beginLayer-restore
+// Description:Raises exception on beginLayer() + restore().
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.restore();
+ });
+ t.done();
+});
+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
new file mode 100644
index 0000000000..26dd0eee4b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.invalid-calls.beginLayer-save-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.invalid-calls.beginLayer-save-endLayer</h1>
+<p class="desc">Raises exception on beginLayer() + save() + endLayer().</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.save();
+ ctx.endLayer();
+ });
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..613921c67c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.worker.js
@@ -0,0 +1,26 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.invalid-calls.beginLayer-save-endLayer
+// Description:Raises exception on beginLayer() + save() + endLayer().
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.save();
+ ctx.endLayer();
+ });
+ t.done();
+});
+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
new file mode 100644
index 0000000000..440249980a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.invalid-calls.endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.invalid-calls.endLayer</h1>
+<p class="desc">Raises exception on lone endLayer calls.</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.endLayer();
+ });
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..b2ba231b9c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.endLayer.worker.js
@@ -0,0 +1,24 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.invalid-calls.endLayer
+// Description:Raises exception on lone endLayer calls.
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.endLayer();
+ });
+ t.done();
+});
+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
new file mode 100644
index 0000000000..c2b09961ac
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.invalid-calls.save-beginLayer-restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.invalid-calls.save-beginLayer-restore</h1>
+<p class="desc">Raises exception on save() + beginLayer() + restore().</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.save();
+ ctx.beginLayer();
+ ctx.restore();
+ });
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..d155379fcb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-beginLayer-restore.worker.js
@@ -0,0 +1,26 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.invalid-calls.save-beginLayer-restore
+// Description:Raises exception on save() + beginLayer() + restore().
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.save();
+ ctx.beginLayer();
+ ctx.restore();
+ });
+ t.done();
+});
+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
new file mode 100644
index 0000000000..01b62d1e85
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.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.layer.invalid-calls.save-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.invalid-calls.save-endLayer</h1>
+<p class="desc">Raises exception on save() + endLayer().</p>
+
+
+<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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.save();
+ ctx.endLayer();
+ });
+ t.done();
+
+});
+</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
new file mode 100644
index 0000000000..353c1b00cd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.invalid-calls.save-endLayer.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.layer.invalid-calls.save-endLayer
+// Description:Raises exception on save() + endLayer().
+// Note:
+
+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() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.save();
+ ctx.endLayer();
+ });
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.html
new file mode 100644
index 0000000000..867553b45e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.layer-rendering-state-reset-in-layer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.layer-rendering-state-reset-in-layer</h1>
+<p class="desc">Tests that layers ignore the global context filter.</p>
+
+
+<script>
+var t = async_test("Tests that layers ignore the global context filter.");
+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.globalAlpha = 0.5;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowColor = '#0000ff';
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 20;
+ ctx.shadowBlur = 30;
+
+ _assertSame(ctx.globalAlpha, 0.5, "ctx.globalAlpha", "0.5");
+ _assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+ _assertSame(ctx.shadowColor, '#0000ff', "ctx.shadowColor", "'#0000ff'");
+ _assertSame(ctx.shadowOffsetX, 10, "ctx.shadowOffsetX", "10");
+ _assertSame(ctx.shadowOffsetY, 20, "ctx.shadowOffsetY", "20");
+ _assertSame(ctx.shadowBlur, 30, "ctx.shadowBlur", "30");
+
+ ctx.beginLayer();
+
+ _assertSame(ctx.globalAlpha, 1.0, "ctx.globalAlpha", "1.0");
+ _assertSame(ctx.globalCompositeOperation, 'source-over', "ctx.globalCompositeOperation", "'source-over'");
+ _assertSame(ctx.shadowColor, 'rgba(0, 0, 0, 0)', "ctx.shadowColor", "'rgba(0, 0, 0, 0)'");
+ _assertSame(ctx.shadowOffsetX, 0, "ctx.shadowOffsetX", "0");
+ _assertSame(ctx.shadowOffsetY, 0, "ctx.shadowOffsetY", "0");
+ _assertSame(ctx.shadowBlur, 0, "ctx.shadowBlur", "0");
+
+ ctx.endLayer();
+
+ _assertSame(ctx.globalAlpha, 0.5, "ctx.globalAlpha", "0.5");
+ _assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+ _assertSame(ctx.shadowColor, '#0000ff', "ctx.shadowColor", "'#0000ff'");
+ _assertSame(ctx.shadowOffsetX, 10, "ctx.shadowOffsetX", "10");
+ _assertSame(ctx.shadowOffsetY, 20, "ctx.shadowOffsetY", "20");
+ _assertSame(ctx.shadowBlur, 30, "ctx.shadowBlur", "30");
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.worker.js
new file mode 100644
index 0000000000..5c2bb73e8f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.layer-rendering-state-reset-in-layer.worker.js
@@ -0,0 +1,52 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.layer-rendering-state-reset-in-layer
+// Description:Tests that layers ignore the global context filter.
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Tests that layers ignore the global context filter.");
+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.globalAlpha = 0.5;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowColor = '#0000ff';
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 20;
+ ctx.shadowBlur = 30;
+
+ _assertSame(ctx.globalAlpha, 0.5, "ctx.globalAlpha", "0.5");
+ _assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+ _assertSame(ctx.shadowColor, '#0000ff', "ctx.shadowColor", "'#0000ff'");
+ _assertSame(ctx.shadowOffsetX, 10, "ctx.shadowOffsetX", "10");
+ _assertSame(ctx.shadowOffsetY, 20, "ctx.shadowOffsetY", "20");
+ _assertSame(ctx.shadowBlur, 30, "ctx.shadowBlur", "30");
+
+ ctx.beginLayer();
+
+ _assertSame(ctx.globalAlpha, 1.0, "ctx.globalAlpha", "1.0");
+ _assertSame(ctx.globalCompositeOperation, 'source-over', "ctx.globalCompositeOperation", "'source-over'");
+ _assertSame(ctx.shadowColor, 'rgba(0, 0, 0, 0)', "ctx.shadowColor", "'rgba(0, 0, 0, 0)'");
+ _assertSame(ctx.shadowOffsetX, 0, "ctx.shadowOffsetX", "0");
+ _assertSame(ctx.shadowOffsetY, 0, "ctx.shadowOffsetY", "0");
+ _assertSame(ctx.shadowBlur, 0, "ctx.shadowBlur", "0");
+
+ ctx.endLayer();
+
+ _assertSame(ctx.globalAlpha, 0.5, "ctx.globalAlpha", "0.5");
+ _assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+ _assertSame(ctx.shadowColor, '#0000ff', "ctx.shadowColor", "'#0000ff'");
+ _assertSame(ctx.shadowOffsetX, 10, "ctx.shadowOffsetX", "10");
+ _assertSame(ctx.shadowOffsetY, 20, "ctx.shadowOffsetY", "20");
+ _assertSame(ctx.shadowBlur, 30, "ctx.shadowBlur", "30");
+ t.done();
+});
+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
new file mode 100644
index 0000000000..0b3854c31d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.html
@@ -0,0 +1,27 @@
+<!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
new file mode 100644
index 0000000000..be0f4f2cde
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.convertToBlob.worker.js
@@ -0,0 +1,23 @@
+// 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());
+ t.done();
+}, "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
new file mode 100644
index 0000000000..085554d9f5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html
@@ -0,0 +1,27 @@
+<!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
new file mode 100644
index 0000000000..b286b7a9e7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.worker.js
@@ -0,0 +1,23 @@
+// 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));
+ t.done();
+}, "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.createPattern.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.html
new file mode 100644
index 0000000000..a206e64ceb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.html
@@ -0,0 +1,34 @@
+<!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
new file mode 100644
index 0000000000..bcb42cba87
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.createPattern.worker.js
@@ -0,0 +1,29 @@
+// 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
new file mode 100644
index 0000000000..e6a9872100
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.html
@@ -0,0 +1,36 @@
+<!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
new file mode 100644
index 0000000000..b66cdee62e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.drawImage.worker.js
@@ -0,0 +1,31 @@
+// 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
new file mode 100644
index 0000000000..87bc8c6ede
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.html
@@ -0,0 +1,34 @@
+<!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
new file mode 100644
index 0000000000..6a1a16fccb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.getImageData.worker.js
@@ -0,0 +1,29 @@
+// 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.putImageData.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.html
new file mode 100644
index 0000000000..e8059076bb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.html
@@ -0,0 +1,37 @@
+<!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
new file mode 100644
index 0000000000..8810c3a73c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.putImageData.worker.js
@@ -0,0 +1,32 @@
+// 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
new file mode 100644
index 0000000000..79c216421f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.html
@@ -0,0 +1,34 @@
+<!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
new file mode 100644
index 0000000000..be0b43665a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.malformed-operations.transferToImageBitmap.worker.js
@@ -0,0 +1,29 @@
+// 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.nested-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-expected.html
new file mode 100644
index 0000000000..65525d4d6a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-expected.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.nested</title>
+<h1>2d.layer.nested</h1>
+<p class="desc">Tests nested canvas layers.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 40, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx2.fillRect(60, 60, 75, 50);
+
+ ctx2.globalAlpha = 0.5;
+
+ canvas3 = document.createElement("canvas");
+ ctx3 = canvas3.getContext("2d");
+
+ ctx3.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx3.fillRect(50, 50, 75, 50);
+ ctx3.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx3.fillRect(70, 70, 75, 50);
+
+ ctx2.drawImage(canvas3, 0, 0);
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters-expected.html
new file mode 100644
index 0000000000..8b53e2dc76
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters-expected.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.nested-filters</title>
+<h1>2d.layer.nested-filters</h1>
+<p class="desc">Checks that nested layers work properly when both apply filters.</p>
+<canvas id="canvas" width="400" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(20, 20, 100, 100);
+ ctx.fillRect(30, 30, 100, 100);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(40, 40, 100, 100);
+ ctx.fillStyle = 'red';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(280, 80, 100, 100);
+ ctx.fillRect(270, 70, 100, 100);
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(260, 60, 100, 100);
+ ctx.fillStyle = 'red';
+ ctx.fillRect(250, 50, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters.html
new file mode 100644
index 0000000000..adf99bacbe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.nested-filters-expected.html">
+<title>Canvas test: 2d.layer.nested-filters</title>
+<h1>2d.layer.nested-filters</h1>
+<p class="desc">Checks that nested layers work properly when both apply filters.</p>
+<canvas id="canvas" width="400" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(400, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -20, dy: -20,
+ stdDeviation: 0, floodColor: 'yellow'}});
+ ctx.beginLayer({filter: 'drop-shadow(-10px -10px 0 blue)'});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'drop-shadow(20px 20px 0 blue)'});
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 10, dy: 10,
+ stdDeviation: 0, floodColor: 'yellow'}});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(250, 50, 100, 100);
+
+ ctx.endLayer();
+ ctx.endLayer();
+
+ 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.nested-filters.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters.w.html
new file mode 100644
index 0000000000..0616fecfd9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested-filters.w.html
@@ -0,0 +1,50 @@
+<!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.nested-filters-expected.html">
+<title>Canvas test: 2d.layer.nested-filters</title>
+<h1>2d.layer.nested-filters</h1>
+<p class="desc">Checks that nested layers work properly when both apply filters.</p>
+<canvas id="canvas" width="400" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(400, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -20, dy: -20,
+ stdDeviation: 0, floodColor: 'yellow'}});
+ ctx.beginLayer({filter: 'drop-shadow(-10px -10px 0 blue)'});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'drop-shadow(20px 20px 0 blue)'});
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 10, dy: 10,
+ stdDeviation: 0, floodColor: 'yellow'}});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(250, 50, 100, 100);
+
+ ctx.endLayer();
+ ctx.endLayer();
+
+ 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.nested.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested.html
new file mode 100644
index 0000000000..9e5b7d5826
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.nested-expected.html">
+<title>Canvas test: 2d.layer.nested</title>
+<h1>2d.layer.nested</h1>
+<p class="desc">Tests nested canvas layers.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 40, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+ ctx.endLayer();
+
+ 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.nested.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested.w.html
new file mode 100644
index 0000000000..99e7390609
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.nested.w.html
@@ -0,0 +1,53 @@
+<!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.nested-expected.html">
+<title>Canvas test: 2d.layer.nested</title>
+<h1>2d.layer.nested</h1>
+<p class="desc">Tests nested canvas layers.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 40, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+ ctx.endLayer();
+
+ 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.opaque-canvas-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas-expected.html
new file mode 100644
index 0000000000..89c85de1e5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.opaque-canvas</title>
+<h1>2d.layer.opaque-canvas</h1>
+<p class="desc">Checks that layer blending works inside opaque canvas</p>
+<canvas id="canvas" width="300" height="300">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 300, 300);
+
+ ctx.fillStyle = 'black';
+ ctx.fillRect(0, 0, 200, 200);
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(10, 10, 100, 100);
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'green';
+ ctx2.fillRect(50, 50, 100, 100);
+ ctx2.globalAlpha = 0.8;
+ ctx2.fillStyle = 'yellow';
+ ctx2.fillRect(75, 25, 100, 100);
+
+ ctx.shadowColor = 'rgba(200, 100, 50, 0.5)';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas.html
new file mode 100644
index 0000000000..f9759abebe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.opaque-canvas-expected.html">
+<title>Canvas test: 2d.layer.opaque-canvas</title>
+<h1>2d.layer.opaque-canvas</h1>
+<p class="desc">Checks that layer blending works inside opaque canvas</p>
+<canvas id="canvas" width="300" height="300">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(300, 300);
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d', {alpha: false});
+
+ ctx2.fillStyle = 'purple';
+ ctx2.fillRect(10, 10, 100, 100);
+
+ ctx2.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: 10,
+ stdDeviation: 0,
+ floodColor: 'rgba(200, 100, 50, 0.5)'}});
+ ctx2.fillStyle = 'green';
+ ctx2.fillRect(50, 50, 100, 100);
+ ctx2.globalAlpha = 0.8;
+ ctx2.fillStyle = 'yellow';
+ ctx2.fillRect(75, 25, 100, 100);
+ ctx2.endLayer();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 300, 300);
+ ctx.drawImage(canvas2, 0, 0);
+
+ 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.opaque-canvas.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas.w.html
new file mode 100644
index 0000000000..ff5ec19418
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.opaque-canvas.w.html
@@ -0,0 +1,50 @@
+<!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.opaque-canvas-expected.html">
+<title>Canvas test: 2d.layer.opaque-canvas</title>
+<h1>2d.layer.opaque-canvas</h1>
+<p class="desc">Checks that layer blending works inside opaque canvas</p>
+<canvas id="canvas" width="300" height="300">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(300, 300);
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d', {alpha: false});
+
+ ctx2.fillStyle = 'purple';
+ ctx2.fillRect(10, 10, 100, 100);
+
+ ctx2.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: 10,
+ stdDeviation: 0,
+ floodColor: 'rgba(200, 100, 50, 0.5)'}});
+ ctx2.fillStyle = 'green';
+ ctx2.fillRect(50, 50, 100, 100);
+ ctx2.globalAlpha = 0.8;
+ ctx2.fillStyle = 'yellow';
+ ctx2.fillRect(75, 25, 100, 100);
+ ctx2.endLayer();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 300, 300);
+ ctx.drawImage(canvas2, 0, 0);
+
+ 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.reset-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset-expected.html
new file mode 100644
index 0000000000..93131dca9c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset-expected.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.reset</title>
+<h1>2d.layer.reset</h1>
+<p class="desc">Checks that reset discards any pending layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillRect(10, 10, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset.html
new file mode 100644
index 0000000000..3254c0a048
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.reset-expected.html">
+<title>Canvas test: 2d.layer.reset</title>
+<h1>2d.layer.reset</h1>
+<p class="desc">Checks that reset discards any pending layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ // Global states:
+ ctx.globalAlpha = 0.3;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -3;
+ ctx.shadowOffsetY = 3;
+ ctx.shadowColor = 'rgba(0, 30, 0, 0.3)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -3, dy: 3}});
+
+ // Layer states:
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -6;
+ ctx.shadowOffsetY = 6;
+ ctx.shadowColor = 'rgba(0, 60, 0, 0.6)';
+ ctx.shadowBlur = 3;
+
+ ctx.reset();
+
+ ctx.fillRect(10, 10, 75, 50);
+
+ 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.reset.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset.w.html
new file mode 100644
index 0000000000..09bd6451bd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.reset.w.html
@@ -0,0 +1,52 @@
+<!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.reset-expected.html">
+<title>Canvas test: 2d.layer.reset</title>
+<h1>2d.layer.reset</h1>
+<p class="desc">Checks that reset discards any pending layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ // Global states:
+ ctx.globalAlpha = 0.3;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -3;
+ ctx.shadowOffsetY = 3;
+ ctx.shadowColor = 'rgba(0, 30, 0, 0.3)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -3, dy: 3}});
+
+ // Layer states:
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -6;
+ ctx.shadowOffsetY = 6;
+ ctx.shadowColor = 'rgba(0, 60, 0, 0.6)';
+ ctx.shadowBlur = 3;
+
+ ctx.reset();
+
+ ctx.fillRect(10, 10, 75, 50);
+
+ 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.restore-style-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style-expected.html
new file mode 100644
index 0000000000..1d0ac3558d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style-expected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.restore-style</title>
+<h1>2d.layer.restore-style</h1>
+<p class="desc">Test that ensure layers restores style values upon endLayer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(60, 60, 75, 50);
+ ctx.drawImage(canvas2, 0, 0);
+
+ ctx.fillRect(70, 70, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style.html
new file mode 100644
index 0000000000..a3593cd2a8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.restore-style-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-950">
+<title>Canvas test: 2d.layer.restore-style</title>
+<h1>2d.layer.restore-style</h1>
+<p class="desc">Test that ensure layers restores style values upon endLayer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0,0,255,1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(70, 70, 75, 50);
+
+ 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.restore-style.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style.w.html
new file mode 100644
index 0000000000..a66fc2bc59
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.restore-style.w.html
@@ -0,0 +1,42 @@
+<!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.restore-style-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-950">
+<title>Canvas test: 2d.layer.restore-style</title>
+<h1>2d.layer.restore-style</h1>
+<p class="desc">Test that ensure layers restores style values upon endLayer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script 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)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(70, 70, 75, 50);
+
+ 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.several-complex-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex-expected.html
new file mode 100644
index 0000000000..ef46f69e2a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.several-complex</title>
+<h1>2d.layer.several-complex</h1>
+<p class="desc">Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers.</p>
+<canvas id="canvas" width="500" height="500">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 95, 70);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'orange';
+ ctx.shadowBlur = 3;
+
+ var canvas2 = [5];
+ var ctx2 = [5];
+
+ for (let i = 0; i < 5; i++) {
+ canvas2[i] = document.createElement("canvas");
+ ctx2[i] = canvas2[i].getContext("2d");
+ ctx2[i].fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2[i].fillRect(60, 40, 75, 50);
+ ctx2[i].fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2[i].fillRect(80, 60, 75, 50);
+
+ ctx.drawImage(canvas2[i], i, i);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex.html
new file mode 100644
index 0000000000..e30f1d2fa0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.several-complex-expected.html">
+<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-6318">
+<title>Canvas test: 2d.layer.several-complex</title>
+<h1>2d.layer.several-complex</h1>
+<p class="desc">Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers.</p>
+<canvas id="canvas" width="500" height="500">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(500, 500);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 95, 70);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'orange';
+ ctx.shadowBlur = 3
+
+ for (let i = 0; i < 5; i++) {
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60 + i, 40 + i, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(80 + i, 60 + i, 75, 50);
+
+ ctx.endLayer();
+ }
+
+ 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.several-complex.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex.w.html
new file mode 100644
index 0000000000..e00de63507
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.several-complex.w.html
@@ -0,0 +1,51 @@
+<!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.several-complex-expected.html">
+<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-6318">
+<title>Canvas test: 2d.layer.several-complex</title>
+<h1>2d.layer.several-complex</h1>
+<p class="desc">Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers.</p>
+<canvas id="canvas" width="500" height="500">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(500, 500);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 95, 70);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'orange';
+ ctx.shadowBlur = 3
+
+ for (let i = 0; i < 5; i++) {
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60 + i, 40 + i, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(80 + i, 60 + i, 75, 50);
+
+ ctx.endLayer();
+ }
+
+ 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.shadow-from-outside-canvas.long-distance-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-expected.html
new file mode 100644
index 0000000000..cc10684a9b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-expected.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ // No clipping.
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html
new file mode 100644
index 0000000000..377dd55ef6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html
new file mode 100644
index 0000000000..98262f53b6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.shadow-from-outside-canvas.long-distance-with-clipping.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.w.html
new file mode 100644
index 0000000000..90b4332f94
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.w.html
@@ -0,0 +1,47 @@
+<!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.shadow-from-outside-canvas.long-distance-with-clipping-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.shadow-from-outside-canvas.long-distance.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance.html
new file mode 100644
index 0000000000..eea9b5dc25
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.long-distance-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.shadow-from-outside-canvas.long-distance.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance.w.html
new file mode 100644
index 0000000000..e4422558cf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.long-distance.w.html
@@ -0,0 +1,45 @@
+<!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.shadow-from-outside-canvas.long-distance-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.shadow-from-outside-canvas.short-distance-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-expected.html
new file mode 100644
index 0000000000..8980708dd1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-expected.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ // No clipping.
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html
new file mode 100644
index 0000000000..024fc8c9a4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html
new file mode 100644
index 0000000000..d5f5b0c8ff
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.shadow-from-outside-canvas.short-distance-with-clipping.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.w.html
new file mode 100644
index 0000000000..acbf09edec
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.w.html
@@ -0,0 +1,47 @@
+<!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.shadow-from-outside-canvas.short-distance-with-clipping-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.shadow-from-outside-canvas.short-distance.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance.html
new file mode 100644
index 0000000000..a1c4689f7e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.short-distance-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.shadow-from-outside-canvas.short-distance.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance.w.html
new file mode 100644
index 0000000000..2e39091f3d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.shadow-from-outside-canvas.short-distance.w.html
@@ -0,0 +1,45 @@
+<!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.shadow-from-outside-canvas.short-distance-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+
+ 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.valid-calls.beginLayer-endLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-endLayer.html
new file mode 100644
index 0000000000..0a6e195ca8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-endLayer.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.beginLayer-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.beginLayer-endLayer</h1>
+<p class="desc">No exception raised on beginLayer() + endLayer().</p>
+
+
+<script>
+var t = async_test("No exception raised on beginLayer() + endLayer().");
+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.beginLayer();
+ ctx.save();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-endLayer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-endLayer.worker.js
new file mode 100644
index 0000000000..a10bcd98b7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-endLayer.worker.js
@@ -0,0 +1,23 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.beginLayer-endLayer
+// Description:No exception raised on beginLayer() + endLayer().
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on beginLayer() + endLayer().");
+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.beginLayer();
+ ctx.save();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.html
new file mode 100644
index 0000000000..12abcc5270
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.beginLayer-save</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.beginLayer-save</h1>
+<p class="desc">No exception raised on beginLayer() + save().</p>
+
+
+<script>
+var t = async_test("No exception raised on beginLayer() + save().");
+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.beginLayer();
+ ctx.save();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.worker.js
new file mode 100644
index 0000000000..03fbeeb4f4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer-save.worker.js
@@ -0,0 +1,23 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.beginLayer-save
+// Description:No exception raised on beginLayer() + save().
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on beginLayer() + save().");
+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.beginLayer();
+ ctx.save();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.html
new file mode 100644
index 0000000000..2178138e8d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.beginLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.beginLayer</h1>
+<p class="desc">No exception raised on lone beginLayer() calls.</p>
+
+
+<script>
+var t = async_test("No exception raised on lone beginLayer() calls.");
+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.beginLayer();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.worker.js
new file mode 100644
index 0000000000..e64be136d7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.beginLayer.worker.js
@@ -0,0 +1,22 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.beginLayer
+// Description:No exception raised on lone beginLayer() calls.
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on lone beginLayer() calls.");
+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.beginLayer();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.html
new file mode 100644
index 0000000000..156dd5abbd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.restore</h1>
+<p class="desc">No exception raised on lone restore() calls.</p>
+
+
+<script>
+var t = async_test("No exception raised on lone restore() calls.");
+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.restore();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.worker.js
new file mode 100644
index 0000000000..7417d12abe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.restore.worker.js
@@ -0,0 +1,22 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.restore
+// Description:No exception raised on lone restore() calls.
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on lone restore() calls.");
+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.restore();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.html
new file mode 100644
index 0000000000..afe735764e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.save-beginLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.save-beginLayer</h1>
+<p class="desc">No exception raised on save() + beginLayer().</p>
+
+
+<script>
+var t = async_test("No exception raised on save() + beginLayer().");
+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.save();
+ ctx.beginLayer();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.worker.js
new file mode 100644
index 0000000000..773ba77a15
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save-beginLayer.worker.js
@@ -0,0 +1,23 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.save-beginLayer
+// Description:No exception raised on save() + beginLayer().
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on save() + beginLayer().");
+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.save();
+ ctx.beginLayer();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.html
new file mode 100644
index 0000000000..2b2de23bb8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.save</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.save</h1>
+<p class="desc">No exception raised on lone save() calls.</p>
+
+
+<script>
+var t = async_test("No exception raised on lone save() calls.");
+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.save();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.worker.js
new file mode 100644
index 0000000000..5bbf0386fe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save.worker.js
@@ -0,0 +1,22 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.save
+// Description:No exception raised on lone save() calls.
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on lone save() calls.");
+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.save();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.html
new file mode 100644
index 0000000000..ec5aa6455e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.save_reset_restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.save_reset_restore</h1>
+<p class="desc">No exception raised on save() + reset() + restore().</p>
+
+
+<script>
+var t = async_test("No exception raised on save() + reset() + restore().");
+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.save();
+ ctx.reset();
+ ctx.restore();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.worker.js
new file mode 100644
index 0000000000..3636c94357
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_reset_restore.worker.js
@@ -0,0 +1,24 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.save_reset_restore
+// Description:No exception raised on save() + reset() + restore().
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on save() + reset() + restore().");
+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.save();
+ ctx.reset();
+ ctx.restore();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.html
new file mode 100644
index 0000000000..1682bca91c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.valid-calls.save_restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.valid-calls.save_restore</h1>
+<p class="desc">No exception raised on save() + restore().</p>
+
+
+<script>
+var t = async_test("No exception raised on save() + restore().");
+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.save();
+ ctx.restore();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.worker.js
new file mode 100644
index 0000000000..8607722df7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.valid-calls.save_restore.worker.js
@@ -0,0 +1,23 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.valid-calls.save_restore
+// Description:No exception raised on save() + restore().
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("No exception raised on save() + restore().");
+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.save();
+ ctx.restore();
+ t.done();
+});
+done();