diff options
Diffstat (limited to '')
31 files changed, 2466 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/convert-to-blob/offscreencanvas.convert.to.blob.html b/testing/web-platform/tests/html/canvas/offscreen/manual/convert-to-blob/offscreencanvas.convert.to.blob.html new file mode 100644 index 0000000000..1cc0e5bffd --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/convert-to-blob/offscreencanvas.convert.to.blob.html @@ -0,0 +1,165 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-converttoblob"> +<script id="myWorker" type="text/worker"> +self.onmessage = function(e) { +}; +</script> +<script> +function makeWorker(script) +{ + var blob = new Blob([script]); + return new Worker(URL.createObjectURL(blob)); +} + +function drawCanvas(ctx) +{ + ctx.fillStyle = "red"; + ctx.fillRect(0, 0, 5, 5); + ctx.fillStyle = "green"; + ctx.fillRect(5, 0, 5, 5); + ctx.fillStyle = "blue"; + ctx.fillRect(0, 5, 5, 5); + ctx.fillStyle = "black"; + ctx.fillRect(5, 5, 5, 5); +} + +function compareImages(image1, image2) +{ + var canvas1 = document.createElement('canvas'); + var canvas2 = document.createElement('canvas'); + canvas1.width = canvas1.height = 10; + canvas2.width = canvas2.height = 10; + var ctx1 = canvas1.getContext('2d'); + var ctx2 = canvas1.getContext('2d'); + ctx1.drawImage(image1, 0, 0); + ctx2.drawImage(image2, 0, 0); + var data1 = ctx1.getImageData(0, 0, 10, 10).data; + var data2 = ctx2.getImageData(0, 0, 10, 10).data; + assert_equals(data1.length, data2.length); + var imageMatched = true; + for (var i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) { + imageMatched = false; + break; + } + } + assert_true(imageMatched); +} + +function testConvertToBlob(t, typeVal, qualityVal) { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var oCtx = offscreenCanvas.getContext('2d'); + drawCanvas(oCtx); + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + drawCanvas(ctx); + var imageLoadedCounter = 0; + + var image1 = new Image(); + var image2 = new Image(); + var promise; + if (typeVal == "empty" && qualityVal == "empty") + promise = offscreenCanvas.convertToBlob(); + else if (typeVal == "empty" && qualityVal != "empty") + promise = offscreenCanvas.convertToBlob({quality: qualityVal}); + else if (typeVal != "empty" && qualityVal == "empty") + promise = offscreenCanvas.convertToBlob({type: typeVal}); + else + promise = offscreenCanvas.convertToBlob({type: typeVal, quality: qualityVal}); + promise.then(function(blob2) { + image2.src = URL.createObjectURL(blob2); + if (typeVal == "empty" && qualityVal == "empty") { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }); + } else if (typeVal == "empty" && qualityVal != "empty") { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }, "image/png", qualityVal); + } else if (typeVal != "empty" && qualityVal == "empty") { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }, typeVal, 1.0); + } else { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }, typeVal, qualityVal); + } + image1.onload = image2.onload = t.step_func(function() { + imageLoadedCounter++; + if (imageLoadedCounter == 2) { + compareImages(image1, image2); + t.done(); + } + }); + }); +} + +async_test(function(t) { + testConvertToBlob(t, "empty", "empty"); + testConvertToBlob(t, "empty", 1.0); + testConvertToBlob(t, "empty", 0.2); +}, "Test that convertToBlob with default type produces correct result"); + +async_test(function(t) { + testConvertToBlob(t, "image/png", "empty"); + testConvertToBlob(t, "image/png", 1.0); + testConvertToBlob(t, "image/png", 0.2); +}, "Test that convertToBlob with png produces correct result"); + +async_test(function(t) { + testConvertToBlob(t, "image/jpeg", "empty"); + testConvertToBlob(t, "image/jpeg", 1.0); + testConvertToBlob(t, "image/jpeg", 0.2); +}, "Test that convertToBlob with jpge produces correct result"); + +async_test(function(t) { + testConvertToBlob(t, "image/webp", "empty"); + testConvertToBlob(t, "image/webp", 1.0); + testConvertToBlob(t, "image/webp", 0.2); +}, "Test that convertToBlob with webp produces correct result"); + +async_test(function(t) { + var worker = makeWorker(document.getElementById("myWorker").textContent); + var offscreenCanvas = new OffscreenCanvas(10, 10); + worker.postMessage({offscreenCanvas}, [offscreenCanvas]); + offscreenCanvas.convertToBlob().then(t.step_func_done(function() { + assert_false("convertToBlob didn't throw, but should be"); + }), t.step_func_done(function(e) { + assert_true(e instanceof DOMException); + assert_equals(e.name, "InvalidStateError"); + })); +}, "Test that call convertToBlob on a detached OffscreenCanvas throws exception"); + +async_test(function(t) { + var offscreenCanvas = new OffscreenCanvas(0, 0); + offscreenCanvas.convertToBlob().then(t.step_func_done(function() { + assert_false("convertToBlob didn't throw, but should be"); + }), t.step_func_done(function(e) { + assert_true(e instanceof DOMException); + assert_equals(e.name, "IndexSizeError"); + })); +}, "Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception"); + +async_test(function(t) { + var img = new Image(); + img.src = "/images/green.png"; + img.crossOrigin = "anonymous"; + img.onload = t.step_func_done(() => { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext("2d"); + ctx.drawImage(img, 0, 0); + offscreenCanvas.convertToBlob().then(t.step_func_done(function() { + assert_false("convertToBlob didn't throw, but should"); + }), t.step_func_done(function(e) { + assert_true(e instanceof DOMException); + assert_equals(e.name, "SecurityError"); + })); + }); +}, "Test that call convertToBlob on a OffscreenCanvas with tainted origin throws exception"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/convert-to-blob/offscreencanvas.convert.to.blob.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/convert-to-blob/offscreencanvas.convert.to.blob.w.html new file mode 100644 index 0000000000..5c1fa4cf40 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/convert-to-blob/offscreencanvas.convert.to.blob.w.html @@ -0,0 +1,337 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-converttoblob"> +<script id="myWorker" type="text/worker"> +function drawCanvas(ctx) +{ + ctx.fillStyle = "red"; + ctx.fillRect(0, 0, 5, 5); + ctx.fillStyle = "green"; + ctx.fillRect(5, 0, 5, 5); + ctx.fillStyle = "blue"; + ctx.fillRect(0, 5, 5, 5); + ctx.fillStyle = "black"; + ctx.fillRect(5, 5, 5, 5); +} + +function testConvertToBlob(typeVal, qualityVal) { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var oCtx = offscreenCanvas.getContext('2d'); + drawCanvas(oCtx); + + var promise; + if (typeVal == "empty" && qualityVal == "empty") + promise = offscreenCanvas.convertToBlob(); + else if (typeVal == "empty" && qualityVal != "empty") + promise = offscreenCanvas.convertToBlob({quality: qualityVal}); + else if (typeVal != "empty" && qualityVal == "empty") + promise = offscreenCanvas.convertToBlob({type: typeVal}); + else + promise = offscreenCanvas.convertToBlob({type: typeVal, quality: qualityVal}); + promise.then(function(blob) { + self.postMessage(blob); + }); +} + +function testConvertToBlobException1() +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + self.postMessage({offscreenCanvas}, [offscreenCanvas]); + offscreenCanvas.convertToBlob().then(function() { + self.postMessage(false); + }, function(e) { + self.postMessage(e instanceof DOMException && e.name == "InvalidStateError"); + }); +} + +function testConvertToBlobException2() +{ + var offscreenCanvas = new OffscreenCanvas(0, 0); + offscreenCanvas.convertToBlob().then(function() { + self.postMessage(false); + }, function(e) { + self.postMessage(e instanceof DOMException && e.name == "IndexSizeError"); + }); +} + +function testConvertToBlobException3(bitmap) +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext("2d"); + ctx.drawImage(bitmap, 0, 0); + offscreenCanvas.convertToBlob().then(function() { + self.postMessage(false); + }, function(e) { + self.postMessage(e instanceof DOMException && e.name == "SecurityError"); + }); +} + +self.onmessage = function(e) { + if (e.data instanceof ImageBitmap) { + testConvertToBlobException3(e.data); + return; + } + + switch(e.data) { + case 'test1': + testConvertToBlob("empty", "empty"); + break; + case 'test2': + testConvertToBlob("empty", 1.0); + break; + case 'test3': + testConvertToBlob("empty", 0.2); + break; + case 'test4': + testConvertToBlob("image/png", "empty"); + break; + case 'test5': + testConvertToBlob("image/png", 1.0); + break; + case 'test6': + testConvertToBlob("image/png", 0.2); + break; + case 'test7': + testConvertToBlob("image/jpeg", "empty"); + break; + case 'test8': + testConvertToBlob("image/jpeg", 1.0); + break; + case 'test9': + testConvertToBlob("image/jpeg", 0.2); + break; + case 'test10': + testConvertToBlob("image/webp", "empty"); + break; + case 'test11': + testConvertToBlob("image/webp", 1.0); + break; + case 'test12': + testConvertToBlob("image/webp", 0.2); + break; + case 'test13': + testConvertToBlobException1(); + break; + case 'test14': + testConvertToBlobException2(); + break; + } +}; + +</script> + +<script> +function makeWorker(test) { + var blob = new Blob([document.getElementById("myWorker").textContent]); + var worker = new Worker(URL.createObjectURL(blob)); + worker.onerror = test.unreached_func("error"); + return worker; +} + +function drawCanvas(ctx) +{ + ctx.fillStyle = "red"; + ctx.fillRect(0, 0, 5, 5); + ctx.fillStyle = "green"; + ctx.fillRect(5, 0, 5, 5); + ctx.fillStyle = "blue"; + ctx.fillRect(0, 5, 5, 5); + ctx.fillStyle = "black"; + ctx.fillRect(5, 5, 5, 5); +} + +function compareImages(image1, image2) +{ + var canvas1 = document.createElement('canvas'); + var canvas2 = document.createElement('canvas'); + canvas1.width = canvas1.height = 10; + canvas2.width = canvas2.height = 10; + var ctx1 = canvas1.getContext('2d'); + var ctx2 = canvas1.getContext('2d'); + ctx1.drawImage(image1, 0, 0); + ctx2.drawImage(image2, 0, 0); + var data1 = ctx1.getImageData(0, 0, 10, 10).data; + var data2 = ctx2.getImageData(0, 0, 10, 10).data; + assert_equals(data1.length, data2.length); + var imageMatched = true; + for (var i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) { + imageMatched = false; + break; + } + } + assert_true(imageMatched); +} + +function compareWithToBlob(t, typeVal, qualityVal, blob2) +{ + var image1 = new Image(); + var image2 = new Image(); + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + drawCanvas(ctx); + var imageLoadedCounter = 0; + + if (typeVal == "empty" && qualityVal == "empty") { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }); + } else if (typeVal == "empty" && qualityVal != "empty") { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }, "image/png", qualityVal); + } else if (typeVal != "empty" && qualityVal == "empty") { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }, typeVal, 1.0); + } else { + canvas.toBlob(function(blob1) { + image1.src = URL.createObjectURL(blob1); + }, typeVal, qualityVal); + } + image2.src = URL.createObjectURL(blob2); + image1.onload = image2.onload = t.step_func(function() { + imageLoadedCounter++; + if (imageLoadedCounter == 2) { + compareImages(image1, image2); + t.done(); + } + }); +} + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "empty", "empty", msg.data); + })); + worker.postMessage('test1'); +}, "Test that convertToBlob with default arguments produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "empty", 1.0, msg.data); + })); + worker.postMessage('test2'); +}, "Test that convertToBlob with default type/1.0 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "empty", 0.2, msg.data); + })); + worker.postMessage('test3'); +}, "Test that convertToBlob with default type/0.2 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/png", "empty", msg.data); + })); + worker.postMessage('test4'); +}, "Test that convertToBlob with png/default quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/png", 1.0, msg.data); + })); + worker.postMessage('test5'); +}, "Test that convertToBlob with png/1.0 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/png", 0.2, msg.data); + })); + worker.postMessage('test6'); +}, "Test that convertToBlob with png/0.2 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/jpeg", "empty", msg.data); + })); + worker.postMessage('test7'); +}, "Test that convertToBlob with jpeg/default quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/jpeg", 1.0, msg.data); + })); + worker.postMessage('test8'); +}, "Test that convertToBlob with jpeg/1.0 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/jpeg", 0.2, msg.data); + })); + worker.postMessage('test9'); +}, "Test that convertToBlob with jpeg/0.2 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/webp", "empty", msg.data); + })); + worker.postMessage('test10'); +}, "Test that convertToBlob with webp/default quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/webp", 1.0, msg.data); + })); + worker.postMessage('test11'); +}, "Test that convertToBlob with webp/1.0 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func(function(msg) { + compareWithToBlob(t, "image/webp", 0.2, msg.data); + })); + worker.postMessage('test12'); +}, "Test that convertToBlob with webp/0.2 quality produces correct result in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + if (msg.data instanceof Object) + return; + assert_true(msg.data); + t.done(); + })); + worker.postMessage('test13'); +}, "Test that call convertToBlob on a detached OffscreenCanvas throws exception in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + t.done(); + })); + worker.postMessage('test14'); +}, "Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception in a worker"); + +async_test(function(t) { + var img = new Image(); + img.src = "/images/green.png"; + img.crossOrigin = "anonymous"; + img.onload = t.step_func_done(() => { + createImageBitmap(img).then(t.step_func_done(bitmap => { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + t.done(); + })); + worker.postMessage(bitmap); + })); + }); +}, "Test that call convertToBlob on a OffscreenCanvas with tainted origin throws exception in a worker"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.html b/testing/web-platform/tests/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.html new file mode 100644 index 0000000000..a5fd7ab066 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<title>OffscreenCanvas test: 2d.text.draw.generic.family</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<script> +function drawCanvas(ctx, family) +{ + ctx.font = '16px ' + family; + ctx.fillText(family, 0, 16); +} + +function testDrawGenericFamily(family) +{ + let offscreenCanvas = new OffscreenCanvas(88, 24); + let oCtx = offscreenCanvas.getContext('2d'); + drawCanvas(oCtx, family); + let canvas = document.createElement('canvas'); + let ctx = canvas.getContext('2d'); + drawCanvas(ctx, family); + + let data1 = oCtx.getImageData(0, 0, 88, 24).data; + let data2 = ctx.getImageData(0, 0, 88, 24).data; + assert_array_equals(data1, data2, + "The image data generated by drawing generic font family '" + family + + "' should be the same for both OffscreenCanvas and regular canvas"); +} + +test(function() { + testDrawGenericFamily('sans-serif'); +}, "Test that drawing sans-serif produces the same result between canvas and OffscreenCanvas"); + +test(function() { + testDrawGenericFamily('serif'); +}, "Test that drawing serif produces the same result between canvas and OffscreenCanvas"); + +test(function() { + testDrawGenericFamily('cursive'); +}, "Test that drawing cursive produces the same result between canvas and OffscreenCanvas"); + +test(function() { + testDrawGenericFamily('fantasy'); +}, "Test that drawing fantasy produces the same result between canvas and OffscreenCanvas"); + +test(function() { + testDrawGenericFamily('monospace'); +}, "Test that drawing monospace produces the same result between canvas and OffscreenCanvas"); +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.w.html new file mode 100644 index 0000000000..7a88c032ad --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.w.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<title>OffscreenCanvas test: 2d.text.draw.generic.family.w</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<script id='myWorker' type='text/worker'> +self.onmessage = function(e) { + let oc = new OffscreenCanvas(88, 24); + let ctx = oc.getContext('2d'); + ctx.font = '32px ' + e.data.family; + ctx.fillText(e.data.family, 0, 16); + self.postMessage(ctx.getImageData(0, 0, 88, 24).data); +}; +</script> +<script> +function testDrawGenericFamily(t, family) +{ + let blob = new Blob([document.getElementById('myWorker').textContent]); + let worker = new Worker(URL.createObjectURL(blob)); + worker.addEventListener('message', msg => { + let ctx = document.createElement('canvas').getContext('2d'); + ctx.font = '32px ' + family; + ctx.fillText(family, 0, 16); + assert_array_equals(ctx.getImageData(0, 0, 88, 24).data, msg.data, + "The image data generated by drawing generic font family '" + family + + "' should be the same for both OffscreenCanvas and regular canvas"); + t.done(); + }); + worker.postMessage({family: family}); +} + +async_test(function(t) { + testDrawGenericFamily(t, 'sans-serif'); +}, "Test that drawing sans-serif produces the same result between canvas and OffscreenCanvas in a Worker"); + +async_test(function(t) { + testDrawGenericFamily(t, 'serif'); +}, "Test that drawing serif produces the same result between canvas and OffscreenCanvas in a Worker"); + +async_test(function(t) { + testDrawGenericFamily(t, 'cursive'); +}, "Test that drawing cursive produces the same result between canvas and OffscreenCanvas in a Worker"); + +async_test(function(t) { + testDrawGenericFamily(t, 'fantasy'); +}, "Test that drawing fantasy produces the same result between canvas and OffscreenCanvas in a Worker"); + +async_test(function(t) { + testDrawGenericFamily(t, 'monospace'); +}, "Test that drawing monospace produces the same result between canvas and OffscreenCanvas in a Worker"); +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.html b/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.html new file mode 100644 index 0000000000..25691983f1 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.html @@ -0,0 +1,27 @@ +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="offscreencanvas.filter.js"></script> +<script> +var patternCanvas = createPatternCanvas(); + +var getOffscreenContextForFilter = function(filter, pattern) { + var oc = new OffscreenCanvas(80, 80); + var offCtx = oc.getContext('2d'); + offCtx.filter = filter; + offCtx.drawImage(pattern, 5, 5); + offCtx.drawImage(pattern, 25, 25); + offCtx.drawImage(pattern, 45, 45); + return offCtx; +}; + +var testFilter = function(filter) { + var offCtx = getOffscreenContextForFilter(filter, patternCanvas); + var ctx = getRegularContextForFilter(filter, patternCanvas); + var offImageData = offCtx.getImageData(0, 0, 80, 80).data; + var imageData = ctx.getImageData(0, 0, 80, 80).data; + matchImageDataResults(offImageData, imageData, filter); +}; + +generate_tests(testFilter, [filters]); + +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.js b/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.js new file mode 100644 index 0000000000..cb2e245803 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.js @@ -0,0 +1,48 @@ +var getRegularContextForFilter = function(filter, pattern) { + var c = document.createElement("canvas"); + c.width = c.height = 80; + var ctx = c.getContext('2d'); + ctx.filter = filter; + ctx.drawImage(pattern, 5, 5); + ctx.drawImage(pattern, 25, 25); + ctx.drawImage(pattern, 45, 45); + return ctx; +}; + +var matchImageDataResults = function(offscreenImage, regularImage, filter) { + assert_array_equals(offscreenImage, regularImage, + "The image data generated by filter " + + filter + + " should be the same for both OffscreenCanvas and regular canvas"); +}; + +var createPatternCanvas = function() { + var patternCanvas = document.createElement('canvas'); + patternCanvas.width = 20; + patternCanvas.height = 20; + var patternCtx = patternCanvas.getContext('2d'); + patternCtx.fillStyle = '#A00'; + patternCtx.fillRect(0, 0, 10, 10); + patternCtx.fillStyle = '#0A0'; + patternCtx.fillRect(10, 0, 10, 10); + patternCtx.fillStyle = '#00A'; + patternCtx.fillRect(0, 10, 10, 10); + patternCtx.fillStyle = "#AA0"; + patternCtx.fillRect(10, 10, 10, 10); + return patternCanvas; +}; + +var filters = [ "none" , + "blur(10px)" , + "brightness(40%)" , + "contrast(20%)" , + "drop-shadow(0 0 5px green)" , + "grayscale(100%)" , + "invert(100%)" , + "opacity(50%)" , + "saturate(20%)" , + "sepia(100%)" , + "sepia(1) hue-rotate(200deg)", + "url(#url)" ]; + + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.w.html new file mode 100644 index 0000000000..d6ed915b53 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.w.html @@ -0,0 +1,54 @@ +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="offscreencanvas.filter.js"></script> +<script id='myWorker' type='text/worker'> +self.onmessage = function(e) { + var getOffscreenCanvasForFilter = function(filter, pattern) { + var oc = new OffscreenCanvas(80, 80); + var offCtx = oc.getContext('2d'); + offCtx.filter = filter; + offCtx.drawImage(pattern, 5, 5); + offCtx.drawImage(pattern, 25, 25); + offCtx.drawImage(pattern, 45, 45); + return oc; + }; + + var filters = e.data.filters; + var pattern = e.data.pattern; + var ret = []; + for (var i = 0; i < filters.length; i++) { + var oc = getOffscreenCanvasForFilter(filters[i], pattern); + var imageBitmap = oc.transferToImageBitmap(); + ret.push(imageBitmap); + } + self.postMessage(ret, ret); +}; +</script> +<script> +var patternCanvas = createPatternCanvas(); + +// Build a list of image data on regular canvas with different filters +var listCanvasImageData = []; +for (var j = 0; j < filters.length; j++) { + var ctx = getRegularContextForFilter(filters[j], patternCanvas); + listCanvasImageData.push(ctx.getImageData(0, 0, 80, 80).data); +} + +function consumeImageBitmap(patternImage) { + async_test(t => { + var blob = new Blob([document.getElementById('myWorker').textContent]); + var worker = new Worker(URL.createObjectURL(blob)); + worker.addEventListener('message', msg => { + for (var i = 0; i < msg.data.length; ++i) { + var outputCtx = document.createElement("canvas").getContext('2d'); + outputCtx.drawImage(msg.data[i], 0, 0, 80, 80); + matchImageDataResults(outputCtx.getImageData(0, 0, 80, 80).data, listCanvasImageData[i], filters[i]); + } + t.done(); + }); + worker.postMessage({filters: filters, pattern: patternImage}, [patternImage]); + }); +} + +createImageBitmap(patternCanvas).then(consumeImageBitmap); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/image-smoothing/image.smoothing.html b/testing/web-platform/tests/html/canvas/offscreen/manual/image-smoothing/image.smoothing.html new file mode 100644 index 0000000000..a78524c51d --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/image-smoothing/image.smoothing.html @@ -0,0 +1,128 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>OffscreenCanvasRenderingContext2D imageSmoothingEnabled test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#the-offscreen-2d-rendering-context"> +<script> +function createTestImage() { + var image = new OffscreenCanvas(100, 50); + var imgctx = image.getContext('2d'); + imgctx.fillStyle = "#F00"; + imgctx.fillRect(0, 0, 2, 2); + imgctx.fillStyle = "#0F0"; + imgctx.fillRect(0, 0, 1, 1); + return image; +} + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + assert_true(ctx.imageSmoothingEnabled); +}, "When the context is created, imageSmoothingEnabled must be set to true."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.imageSmoothingEnabled = false; + assert_false(ctx.imageSmoothingEnabled); +}, "On getting imageSmoothingEnabled, the user agent must return the last value it was set to."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_not_equals(pixels[0], 0); + assert_not_equals(pixels[1], 255); +}, "Test that image smoothing is actually on by default."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.imageSmoothingEnabled = true; + var image = createTestImage(); + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_not_equals(pixels[0], 0); + assert_not_equals(pixels[1], 255); +}, "Test that image smoothing works when imageSmoothingEnabled is set to true"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with drawImage()."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.fillStyle = ctx.createPattern(image, 'repeat'); + ctx.fillRect(0, 0, 10, 10); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with fillRect and createPattern()."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.fillStyle = ctx.createPattern(image, 'repeat'); + ctx.scale(10, 10); + ctx.rect(0, 0, 10, 10); + ctx.fill(); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with fill() and createPattern()."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.strokeStyle = ctx.createPattern(image, 'repeat'); + ctx.lineWidth = 5; + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(10, 10); + ctx.stroke(); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with stroke() and createPattern()."); + +test(function() { + var repaints = 5; + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + + function draw() { + ctx.clearRect(0, 0, 10, 10); + ctx.setTransform(1, 0, 0, 1, 0, 0); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); + } + + while (repaints > 0) { + draw(); + repaints = repaints - 1; + } + +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) still works after repaints."); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/image-smoothing/image.smoothing.worker.js b/testing/web-platform/tests/html/canvas/offscreen/manual/image-smoothing/image.smoothing.worker.js new file mode 100644 index 0000000000..4c37e84b1f --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/image-smoothing/image.smoothing.worker.js @@ -0,0 +1,126 @@ +// spec link: https://html.spec.whatwg.org/#the-offscreen-2d-rendering-context + +importScripts("/resources/testharness.js"); + +function createTestImage() { + var image = new OffscreenCanvas(100, 50); + var imgctx = image.getContext('2d'); + imgctx.fillStyle = "#F00"; + imgctx.fillRect(0, 0, 2, 2); + imgctx.fillStyle = "#0F0"; + imgctx.fillRect(0, 0, 1, 1); + return image; +} + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + assert_true(ctx.imageSmoothingEnabled); +}, "When the context is created, imageSmoothingEnabled must be set to true."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.imageSmoothingEnabled = false; + assert_false(ctx.imageSmoothingEnabled); +}, "On getting imageSmoothingEnabled, the user agent must return the last value it was set to."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_not_equals(pixels[0], 0); + assert_not_equals(pixels[1], 255); +}, "Test that image smoothing is actually on by default."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.imageSmoothingEnabled = true; + var image = createTestImage(); + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_not_equals(pixels[0], 0); + assert_not_equals(pixels[1], 255); +}, "Test that image smoothing works when imageSmoothingEnabled is set to true"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with drawImage()."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.fillStyle = ctx.createPattern(image, 'repeat'); + ctx.fillRect(0, 0, 10, 10); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with fillRect and createPattern()."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.fillStyle = ctx.createPattern(image, 'repeat'); + ctx.scale(10, 10); + ctx.rect(0, 0, 10, 10); + ctx.fill(); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with fill() and createPattern()."); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + var image = createTestImage(); + ctx.strokeStyle = ctx.createPattern(image, 'repeat'); + ctx.lineWidth = 5; + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(10, 10); + ctx.stroke(); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with stroke() and createPattern()."); + +test(function() { + var repaints = 5; + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + + function draw() { + ctx.clearRect(0, 0, 10, 10); + ctx.setTransform(1, 0, 0, 1, 0, 0); + var image = createTestImage(); + ctx.imageSmoothingEnabled = false; + ctx.scale(10, 10); + ctx.drawImage(image, 0, 0); + var pixels = ctx.getImageData(9, 9, 1, 1).data; + assert_array_equals(pixels, [0, 255, 0, 255]); + } + + while (repaints > 0) { + draw(); + repaints = repaints - 1; + } + +}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) still works after repaints."); + +done(); diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers-expected.html b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers-expected.html new file mode 100644 index 0000000000..873869ea72 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers-expected.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title>Canvas test: unclosed-layers</title> +<h1>unclosed-layers</h1> +<p class="desc">Check that unclosed layers aren't rendered.</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 = 'purple'; + ctx.fillRect(60, 60, 75, 50); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers.html b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers.html new file mode 100644 index 0000000000..4fee600d6c --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="match" href="unclosed-layers-expected.html"> +<title>Canvas test: unclosed-layers</title> +<h1>unclosed-layers</h1> +<p class="desc">Check that unclosed layers aren't rendered.</p> +<canvas id="canvas" width="1" height="1"> + <p class="fallback">FAIL (fallback content)</p> +</canvas> +<script> + var placeholder = document.getElementById('canvas'); + var offscreen = placeholder.transferControlToOffscreen(); + const ctx = offscreen.getContext('2d'); + offscreen.width = offscreen.height = 200; + + ctx.fillStyle = 'purple'; + ctx.fillRect(60, 60, 75, 50); + + ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); + ctx.fillRect(40, 40, 75, 50); + ctx.fillStyle = 'grey'; + ctx.fillRect(50, 50, 75, 50); + + function draw () { + // Wait until frame propagates. + if(placeholder.width != 200) { + requestAnimationFrame(draw); + } else { + document.documentElement.classList.remove("reftest-wait"); + } + } + requestAnimationFrame(draw); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers.w.html new file mode 100644 index 0000000000..a0014bb597 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-layers.w.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="match" href="unclosed-layers-expected.html"> +<title>Canvas test: unclosed-layers</title> +<h1>unclosed-layers</h1> +<p class="desc">Check that unclosed layers aren't rendered.</p> +<canvas id="canvas" width="1" height="1"> + <p class="fallback">FAIL (fallback content)</p> +</canvas> +<script id='myWorker' type='text/worker'> + self.onmessage = msg => { + const offscreen = msg.data.canvas; + const ctx = offscreen.getContext('2d'); + offscreen.width = offscreen.height = 200; + + ctx.fillStyle = 'purple'; + ctx.fillRect(60, 60, 75, 50); + + ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); + ctx.fillRect(40, 40, 75, 50); + ctx.fillStyle = 'grey'; + ctx.fillRect(50, 50, 75, 50); + + self.postMessage('setup ready'); + } +</script> +<script> + const blob = new Blob([document.getElementById('myWorker').textContent]); + const worker = new Worker(URL.createObjectURL(blob)); + var placeholder = document.getElementById('canvas'); + var offscreen = placeholder.transferControlToOffscreen(); + worker.addEventListener('message', msg => { + if(msg.data == 'setup ready') { + function draw () { + // Wait until frame propagates. + if(placeholder.width != 1) { + document.documentElement.classList.remove("reftest-wait"); + } else { + requestAnimationFrame(draw); + } + } + requestAnimationFrame(draw); + } + }); + worker.postMessage({ + canvas: offscreen + }, [offscreen]); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers-expected.html b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers-expected.html new file mode 100644 index 0000000000..8557441f7e --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers-expected.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title>Canvas test: unclosed-nested-layers</title> +<h1>unclosed-nested-layers</h1> +<p class="desc">Check that unclosed nested layers aren't rendered.</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(60,60,75,50); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers.html b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers.html new file mode 100644 index 0000000000..c6925beb74 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="match" href="unclosed-nested-layers-expected.html"> +<title>Canvas test: unclosed-nested-layers</title> +<h1>unclosed-nested-layers</h1> +<p class="desc">Check that unclosed nested layers aren't rendered.</p> +<canvas id="canvas" width="1" height="1"> + <p class="fallback">FAIL (fallback content)</p> +</canvas> +<script> + var placeholder = document.getElementById('canvas'); + var offscreen = placeholder.transferControlToOffscreen(); + const ctx = offscreen.getContext('2d'); + offscreen.width = offscreen.height = 200; + + ctx.fillStyle = 'rgba(0, 0, 255, 1)'; + ctx.fillRect(60, 60, 75, 50); + + ctx.beginLayer(); + ctx.fillStyle = 'rgba(225, 0, 0, 1)'; + ctx.fillRect(50, 50, 75, 50); + + ctx.beginLayer(); + ctx.fillStyle = 'rgba(0, 255, 0, 1)'; + ctx.fillRect(70, 70, 75, 50); + + ctx.endLayer(); + // Missing ctx.endLayer() here. + + function draw () { + // Wait until frame propagates. + if(placeholder.width != 200) { + requestAnimationFrame(draw); + } else { + document.documentElement.classList.remove("reftest-wait"); + } + } + requestAnimationFrame(draw); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers.w.html new file mode 100644 index 0000000000..1a1dc54052 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/layers/unclosed-nested-layers.w.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="match" href="unclosed-nested-layers-expected.html"> +<title>Canvas test: unclosed-nested-layers</title> +<h1>unclosed-nested-layers</h1> +<p class="desc">Check that unclosed nested layers aren't rendered.</p> +<canvas id="canvas" width="1" height="1"> + <p class="fallback">FAIL (fallback content)</p> +</canvas> +<script id='myWorker' type='text/worker'> + self.onmessage = msg => { + const offscreen = msg.data.canvas; + const ctx = offscreen.getContext('2d'); + offscreen.width = offscreen.height = 200; + + ctx.fillStyle = 'rgba(0, 0, 255, 1)'; + ctx.fillRect(60, 60, 75, 50); + + ctx.beginLayer(); + ctx.fillStyle = 'rgba(225, 0, 0, 1)'; + ctx.fillRect(50, 50, 75, 50); + + ctx.beginLayer(); + ctx.fillStyle = 'rgba(0, 255, 0, 1)'; + ctx.fillRect(70, 70, 75, 50); + + ctx.endLayer(); + // Missing ctx.endLayer() here. + + self.postMessage('setup ready'); + } +</script> +<script> + const blob = new Blob([document.getElementById('myWorker').textContent]); + const worker = new Worker(URL.createObjectURL(blob)); + var placeholder = document.getElementById('canvas'); + var offscreen = placeholder.transferControlToOffscreen(); + worker.addEventListener('message', msg => { + if(msg.data == 'setup ready') { + function draw () { + // Wait until frame propagates. + if(placeholder.width != 1) { + document.documentElement.classList.remove("reftest-wait"); + } else { + requestAnimationFrame(draw); + } + } + requestAnimationFrame(draw); + } + }); + worker.postMessage({ + canvas: offscreen + }, [offscreen]); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas-worker-font-load-crash.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas-worker-font-load-crash.html new file mode 100644 index 0000000000..1baf7847de --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas-worker-font-load-crash.html @@ -0,0 +1,19 @@ +<!doctype html> +<html class="test-wait reftest-wait"> +<script> + let url = URL.createObjectURL(new Blob([` + let font = new FontFace('Ahem', 'url(/fonts/Ahem.ttf)'); + self.fonts.add(font); + let canvas = new OffscreenCanvas(100, 100); + let ctx = canvas.getContext('2d'); + ctx.font = "10px Ahem"; + ctx.fillText('Hello', 0, 10); + postMessage('done'); + `], { type: "application/javascript" })); + var worker = new Worker(url); + worker.onmessage = function() { + worker.terminate(); + URL.revokeObjectURL(url); + document.documentElement.className = ""; + }; +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.html new file mode 100644 index 0000000000..a2ad1dcc7e --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas"> +<script> + +test(function() { + assert_throws_js( + TypeError, + () => OffscreenCanvas(100, 50), + "Calling OffscreenCanvas constructor without 'new' must throw" + ); +}, "OffscreenCanvas constructor called as normal function"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + assert_equals(offscreenCanvas.width, 100); + assert_equals(offscreenCanvas.height, 50); + + offscreenCanvas.width = 50; + offscreenCanvas.height = 100; + assert_equals(offscreenCanvas.width, 50); + assert_equals(offscreenCanvas.height, 100); +}, "Test that calling OffscreenCanvas's constructor generates correct width and height."); + +test(function() { + var offscreenCanvas1 = new OffscreenCanvas(1, 1); + + offscreenCanvas1.width = null; + offscreenCanvas1.height = null; + assert_equals(offscreenCanvas1.width, 0); + assert_equals(offscreenCanvas1.height, 0); + + assert_throws_js(TypeError, function() { new OffscreenCanvas(-1, -1); }); + + var offscreenCanvas2 = new OffscreenCanvas(null, null); + assert_equals(offscreenCanvas2.width, 0); + assert_equals(offscreenCanvas2.height, 0); + + assert_throws_js(TypeError, function() { offscreenCanvas2.width = -1; }); + assert_throws_js(TypeError, function() { offscreenCanvas2.height = -1; }); + + var obj = {Name: "John Doe", Age: 30}; + assert_throws_js(TypeError, function() { offscreenCanvas2.width = obj; }); + assert_throws_js(TypeError, function() { offscreenCanvas2.height = obj; }); + assert_throws_js(TypeError, function() { new OffscreenCanvas(obj, obj); }); +}, "Test that OffscreenCanvas constructor handles invalid arguments correctly"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.worker.js b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.worker.js new file mode 100644 index 0000000000..72cfb728f0 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.worker.js @@ -0,0 +1,45 @@ +// spec link: https://html.spec.whatwg.org/#dom-offscreencanvas + +importScripts("/resources/testharness.js"); +importScripts("/html/canvas/resources/canvas-tests.js"); + +var t1 = async_test("Test that calling OffscreenCanvas's constructor generates correct width and height."); +t1.step(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + assert_equals(offscreenCanvas.width, 100); + assert_equals(offscreenCanvas.height, 50); + + offscreenCanvas.width = 50; + offscreenCanvas.height = 100; + assert_equals(offscreenCanvas.width, 50); + assert_equals(offscreenCanvas.height, 100); + t1.done(); +}); + +var t2 = async_test("Test that OffscreenCanvas constructor handles invalid arguments correctly in a worker"); +t2.step(function() { + var offscreenCanvas1 = new OffscreenCanvas(1, 1); + + offscreenCanvas1.width = null; + offscreenCanvas1.height = null; + assert_equals(offscreenCanvas1.width, 0); + assert_equals(offscreenCanvas1.height, 0); + + assert_throws_js(TypeError, function() { new OffscreenCanvas(-1, -1); }); + + var offscreenCanvas2 = new OffscreenCanvas(null, null); + assert_equals(offscreenCanvas2.width, 0); + assert_equals(offscreenCanvas2.height, 0); + + assert_throws_js(TypeError, function() { offscreenCanvas2.width = -1; }); + assert_throws_js(TypeError, function() { offscreenCanvas2.height = -1; }); + + var obj = {Name: "John Doe", Age: 30}; + assert_throws_js(TypeError, function() { offscreenCanvas2.width = obj; }); + assert_throws_js(TypeError, function() { offscreenCanvas2.height = obj; }); + assert_throws_js(TypeError, function() { new OffscreenCanvas(obj, obj); }); + t2.done(); +}); + +done(); + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html new file mode 100644 index 0000000000..51c167ddca --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html @@ -0,0 +1,80 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-getcontext"> +<script> + +test(function() { + var offscreenCanvas = new OffscreenCanvas(1, 1); + assert_throws_js(TypeError, function() { offscreenCanvas.getContext('3d'); }); +}, "Test that getContext with un-supported string throws a TypeError."); + +test(function() { + var offscreenCanvas1 = new OffscreenCanvas(1, 1); + var ctx1 = offscreenCanvas1.getContext('2d'); + assert_true(ctx1 instanceof OffscreenCanvasRenderingContext2D); + + var offscreenCanvas2 = new OffscreenCanvas(1, 1); + var ctx2 = offscreenCanvas2.getContext('webgl'); + assert_true(ctx2 instanceof WebGLRenderingContext); + + var offscreenCanvas3 = new OffscreenCanvas(1, 1); + var ctx3 = offscreenCanvas3.getContext('webgl2'); + assert_true(ctx3 instanceof WebGL2RenderingContext); +}, "Test that getContext with supported string returns correct results"); + +test(function() { + var offscreenCanvas1 = new OffscreenCanvas(1, 1); + var ctx1 = offscreenCanvas1.getContext('2d'); + var ctx2 = offscreenCanvas1.getContext('webgl'); + assert_equals(ctx2, null); + + var offscreenCanvas2 = new OffscreenCanvas(1, 1); + var ctx3 = offscreenCanvas2.getContext('webgl'); + var ctx4 = offscreenCanvas2.getContext('2d'); + assert_equals(ctx4, null); +}, "Test that getContext twice with different context type returns null the second time"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(1, 2); + var ctx = offscreenCanvas.getContext('2d'); + var dstCanvas = ctx.canvas; + assert_equals(dstCanvas.width, 1); + assert_equals(dstCanvas.height, 2); +}, "Test that 2dcontext.canvas should return the original OffscreenCanvas"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(1, 2); + var ctx = offscreenCanvas.getContext('webgl'); + var dstCanvas = ctx.canvas; + assert_equals(dstCanvas.width, 1); + assert_equals(dstCanvas.height, 2); +}, "Test that webglcontext.canvas should return the original OffscreenCanvas"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('2d', {alpha: false}); + ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(offscreenCanvas, 5,5, 0,127,0,255, 2); +}, "Test that OffscreenCanvasRenderingContext2D with alpha disabled makes the OffscreenCanvas opaque"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('2d', {alpha: true}); + ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(offscreenCanvas, 5,5, 0,255,0,127, 2); +}, "Test that OffscreenCanvasRenderingContext2D with alpha enabled preserves the alpha"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('2d'); + ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(offscreenCanvas, 5,5, 0,255,0,127, 2); +}, "Test that 'alpha' context creation attribute is true by default"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js new file mode 100644 index 0000000000..c413791f61 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js @@ -0,0 +1,77 @@ +// spec link: https://html.spec.whatwg.org/#dom-offscreencanvas-getcontext + +importScripts("/resources/testharness.js"); +importScripts("/html/canvas/resources/canvas-tests.js"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(1, 1); + assert_throws_js(TypeError, function() { offscreenCanvas.getContext('3d'); }); +}, "Test that getContext with un-supported string throws a TypeError."); + +test(function() { + var offscreenCanvas1 = new OffscreenCanvas(1, 1); + var ctx1 = offscreenCanvas1.getContext('2d'); + assert_true(ctx1 instanceof OffscreenCanvasRenderingContext2D); + + var offscreenCanvas2 = new OffscreenCanvas(1, 1); + var ctx2 = offscreenCanvas2.getContext('webgl'); + assert_true(ctx2 instanceof WebGLRenderingContext); + + var offscreenCanvas3 = new OffscreenCanvas(1, 1); + var ctx3 = offscreenCanvas3.getContext('webgl2'); + assert_true(ctx3 instanceof WebGL2RenderingContext); +}, "Test that getContext with supported string returns correct results"); + +test(function() { + var offscreenCanvas1 = new OffscreenCanvas(1, 1); + var ctx1 = offscreenCanvas1.getContext('2d'); + var ctx2 = offscreenCanvas1.getContext('webgl'); + assert_equals(ctx2, null); + + var offscreenCanvas2 = new OffscreenCanvas(1, 1); + var ctx3 = offscreenCanvas2.getContext('webgl'); + var ctx4 = offscreenCanvas2.getContext('2d'); + assert_equals(ctx4, null); +}, "Test that getContext twice with different context type returns null the second time"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(1, 2); + var ctx = offscreenCanvas.getContext('2d'); + var dstCanvas = ctx.canvas; + assert_equals(dstCanvas.width, 1); + assert_equals(dstCanvas.height, 2); +}, "Test that 2dcontext.canvas should return the original OffscreenCanvas"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(1, 2); + var ctx = offscreenCanvas.getContext('webgl'); + var dstCanvas = ctx.canvas; + assert_equals(dstCanvas.width, 1); + assert_equals(dstCanvas.height, 2); +}, "Test that webglcontext.canvas should return the original OffscreenCanvas"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('2d', {alpha: false}); + ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(offscreenCanvas, 5,5, 0,127,0,255, 2); +}, "Test that OffscreenCanvasRenderingContext2D with alpha disabled makes the OffscreenCanvas opaque"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('2d', {alpha: true}); + ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(offscreenCanvas, 5,5, 0,255,0,127, 2); +}, "Test that OffscreenCanvasRenderingContext2D with alpha enabled preserves the alpha"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('2d'); + ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(offscreenCanvas, 5,5, 0,255,0,127, 2); +}, "Test that 'alpha' context creation attribute is true by default"); + +done(); diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html new file mode 100644 index 0000000000..3ff0eea153 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html @@ -0,0 +1,240 @@ +<!DOCTYPE html> +<title>Test resizing an OffscreenCanvas with a 2d context</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<body></body> +<script> +test(function() { + var canvas = new OffscreenCanvas(10, 20); + canvas.width = 30; + canvas.height = 40; + assert_equals(canvas.width, 30); + assert_equals(canvas.height, 40); +}, "Verify that writing to the width and height attributes of an OffscreenCanvas works when there is no context attached."); + +test(function() { + var canvas = new OffscreenCanvas(10, 20); + canvas.getContext('2d'); + canvas.width = 30; + canvas.height = 40; + assert_equals(canvas.width, 30); + assert_equals(canvas.height, 40); + var image = canvas.transferToImageBitmap(); + assert_equals(image.width, 30); + assert_equals(image.height, 40); +}, "Verify that writing to the width and height attributes of an OffscreenCanvas works when there is a 2d context attached."); + +test(function() { + var canvas = new OffscreenCanvas(10, 20); + canvas.getContext('webgl'); + canvas.width = 30; + canvas.height = 40; + assert_equals(canvas.width, 30); + assert_equals(canvas.height, 40); + var image = canvas.transferToImageBitmap(); + assert_equals(image.width, 30); + assert_equals(image.height, 40); +}, "Verify that writing to the width and height attributes of an OffscreenCanvas works when there is a webgl context attached."); + +test(function() { + var placeholder = document.createElement('canvas'); + placeholder.width = 2; + placeholder.height = 2; + var offscreen = placeholder.transferControlToOffscreen(); + assert_throws_dom("InvalidStateError", () => { placeholder.width = 1; }); + assert_throws_dom("InvalidStateError", () => { placeholder.height = 1; }); +}, "Verify that writing to the width or height attribute of a placeholder canvas throws an exception"); + +test(function() { + var placeholder = document.createElement('canvas'); + placeholder.width = 1; + placeholder.height = 1; + var offscreen = placeholder.transferControlToOffscreen(); + assert_throws_dom("InvalidStateError", () => { placeholder.width = 1; }); + assert_throws_dom("InvalidStateError", () => { placeholder.height = 1; }); +}, "Verify that writing to the width or height attribute of a placeholder canvas throws an exception even when not changing the value of the attribute."); + +test(function() { + var canvas = new OffscreenCanvas(10, 20); + var ctx = canvas.getContext('2d'); + ctx.lineWidth = 5; + canvas.width = 30; + assert_equals(ctx.lineWidth, 1); + ctx.lineWidth = 5; + canvas.height = 40; + assert_equals(ctx.lineWidth, 1); +}, "Verify that resizing a 2d context resets its state."); + +test(function() { + var canvas = new OffscreenCanvas(10, 20); + var ctx = canvas.getContext('2d'); + ctx.lineWidth = 5; + canvas.width = canvas.width; + assert_equals(ctx.lineWidth, 1); + ctx.lineWidth = 5; + canvas.height = canvas.height; + assert_equals(ctx.lineWidth, 1); +}, "Verify that setting the size of a 2d context to the same size it already had resets its state."); + +async_test(function(t) { + var placeholder = document.createElement('canvas'); + document.body.appendChild(placeholder); // So that we can check computed style/ + placeholder.width = 10; + placeholder.height = 20; + var offscreen = placeholder.transferControlToOffscreen(); + var ctx = offscreen.getContext('2d'); + t.step(function() { + // Verify that setting the size of an OffscreenCanvas that has a placeholder works. + offscreen.width = 30; + offscreen.height = 40; + assert_equals(offscreen.width, 30); + assert_equals(offscreen.height, 40); + var image = offscreen.transferToImageBitmap(); + assert_equals(image.width, 30); + assert_equals(image.height, 40); + }); + t.step(function() { + // Verify that setting the size of an OffscreenCanvas does not directly update the size of its placeholder canvas. + assert_equals(placeholder.width, 10); + assert_equals(placeholder.height, 20); + }); + var asyncStepsCompleted = 0; + createImageBitmap(placeholder).then(image => { + t.step(function() { + // Verify that the placeholder was not updated synchronously. + assert_equals(image.width, 10); + assert_equals(image.height, 20); + }); + asyncStepsCompleted = asyncStepsCompleted + 1; + if (asyncStepsCompleted == 2) { + t.done(); + } + }); + + function testImage() { + if (placeholder.width != 30) { + requestAnimationFrame(testImage); + } else { + t.step(function() { + assert_equals(placeholder.width, 30); + assert_equals(placeholder.height, 40); + var computedStyle = window.getComputedStyle(placeholder); + assert_equals(computedStyle.getPropertyValue('width'), "30px"); + assert_equals(computedStyle.getPropertyValue('height'), "40px"); + }); + createImageBitmap(placeholder).then(image => { + t.step(function() { + // Verify that an image grabbed from the placeholder has the correct dimensions + assert_equals(image.width, 30); + assert_equals(image.height, 40); + }); + asyncStepsCompleted = asyncStepsCompleted + 1; + if (asyncStepsCompleted == 2) { + t.done(); + } + }); + } + } + + requestAnimationFrame(testImage); +}, "Verify that resizing an OffscreenCanvas with a 2d context propagates the new size to its placeholder canvas asynchronously."); + +async_test(function(t) { + var placeholder = document.createElement('canvas'); + document.body.appendChild(placeholder); // So that we can check computed style/ + placeholder.width = 10; + placeholder.height = 20; + var offscreen = placeholder.transferControlToOffscreen(); + var ctx = offscreen.getContext('webgl'); + t.step(function() { + // Verify that setting the size of an OffscreenCanvas that has a placeholder works. + offscreen.width = 30; + offscreen.height = 40; + assert_equals(offscreen.width, 30); + assert_equals(offscreen.height, 40); + var image = offscreen.transferToImageBitmap(); + assert_equals(image.width, 30); + assert_equals(image.height, 40); + }); + t.step(function() { + // Verify that setting the size of an OffscreenCanvas does not directly update the size of its placeholder canvas. + assert_equals(placeholder.width, 10); + assert_equals(placeholder.height, 20); + }); + var asyncStepsCompleted = 0; + createImageBitmap(placeholder).then(image => { + t.step(function() { + // Verify that the placeholder was not updated synchronously. + assert_equals(image.width, 10); + assert_equals(image.height, 20); + }); + asyncStepsCompleted = asyncStepsCompleted + 1; + if (asyncStepsCompleted == 2) { + t.done(); + } + }); + + function testImage() { + if (placeholder.width != 30) { + requestAnimationFrame(testImage); + } else { + t.step(function() { + assert_equals(placeholder.width, 30); + assert_equals(placeholder.height, 40); + var computedStyle = window.getComputedStyle(placeholder); + assert_equals(computedStyle.getPropertyValue('width'), "30px"); + assert_equals(computedStyle.getPropertyValue('height'), "40px"); + }); + createImageBitmap(placeholder).then(image => { + t.step(function() { + // Verify that an image grabbed from the placeholder has the correct dimensions + assert_equals(image.width, 30); + assert_equals(image.height, 40); + }); + asyncStepsCompleted = asyncStepsCompleted + 1; + if (asyncStepsCompleted == 2) { + t.done(); + } + }); + } + } + requestAnimationFrame(testImage); +}, "Verify that resizing an OffscreenCanvas with a webgl context propagates the new size to its placeholder canvas asynchronously."); + +async_test(function(t){ + var placeholder = document.createElement('canvas'); + placeholder.width = 1; + placeholder.height = 1; + var offscreen = placeholder.transferControlToOffscreen(); + var ctx = offscreen.getContext('2d'); + offscreen.width = offscreen.height = 10; + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 10, 10); + + var testCanvas = document.createElement('canvas'); + testCanvas.width = testCanvas.height = 20; + var testCtx = testCanvas.getContext('2d'); + + function testImage() { + if (placeholder.width != 10) { + requestAnimationFrame(testImage); + } else { + testCtx.drawImage(placeholder, 0, 0); + var pixel1 = testCtx.getImageData(9, 9, 1, 1).data; + var pixel2 = testCtx.getImageData(9, 10, 1, 1).data; + var pixel3 = testCtx.getImageData(10, 9, 1, 1).data; + t.step(function() { + assert_equals(placeholder.width, 10); + assert_equals(placeholder.height, 10); + assert_array_equals(pixel1, [0, 255, 0, 255]); + assert_array_equals(pixel2, [0, 0, 0, 0]); + assert_array_equals(pixel3, [0, 0, 0, 0]); + }); + t.done(); + } + } + + requestAnimationFrame(testImage); +}, "Verify that drawImage uses the size of the frame as the intinsic size of a placeholder canvas."); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.lowlatency.nocrash.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.lowlatency.nocrash.html new file mode 100644 index 0000000000..1960841564 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.lowlatency.nocrash.html @@ -0,0 +1,12 @@ +<title>Transfer Low-Latency Canvas</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<body></body> + +<script> +test(function(t) { + var ctx = document.createElement("canvas").getContext('2d', {desynchronized:true}); + assert_throws_dom("InvalidStateError", () => { ctx.canvas.transferControlToOffscreen(); }); +}, "Tests that transferring a low latency canvas does not cause a crash. See crbug.com/1255153"); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.html new file mode 100644 index 0000000000..6e1adf9591 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.html @@ -0,0 +1,112 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-transfertoimagebitmap"> + +<script id="myWorker" type="text/worker"> + +self.onmessage = function(e) { +}; + +</script> + +<script> +function makeWorker(script) +{ + var blob = new Blob([script]); + return new Worker(URL.createObjectURL(blob)); +} + +test(function() { + function testSize(contextType) { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext(contextType); + var image = offscreenCanvas.transferToImageBitmap(); + assert_equals(image.width, 100); + assert_equals(image.height, 50); + } + + testSize('2d'); + testSize('webgl'); +}, "Test that transferToImageBitmap returns an ImageBitmap with correct width and height"); + +test(function() { + function testImageBitmapClr(shouldCallTwice, alphaVal) { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d', {alpha: alphaVal}); + ctx.fillStyle = "#0f0"; + ctx.fillRect(0, 0, 100, 50); + var image = offscreenCanvas.transferToImageBitmap(); + + if (shouldCallTwice) + image = offscreenCanvas.transferToImageBitmap(); + + var drawCanvas = document.createElement('canvas'); + drawCanvas.width = 100; + drawCanvas.height = 50; + var dCtx = drawCanvas.getContext('2d'); + dCtx.drawImage(image, 0, 0); + + if (shouldCallTwice) { + if (alphaVal) + _assertPixel(drawCanvas, 50,25, 0,0,0,0); + else + _assertPixel(drawCanvas, 50,25, 0,0,0,255); + } else { + _assertPixel(drawCanvas, 50,25, 0,255,0,255); + } + } + + testImageBitmapClr(false, true); + testImageBitmapClr(true, true); + testImageBitmapClr(true, false); +}, "Test that transferToImageBitmap returns an ImageBitmap with correct color"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.lineWidth = 10; + var image = offscreenCanvas.transferToImageBitmap(); + assert_equals(ctx.lineWidth, 10); +}, "Test that transferToImageBitmap won't change context's property"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.rect(0, 0, 25, 50); + ctx.clip(); + ctx.translate(20, 20); + + ctx.fillStyle = '#0f0'; + var image1 = offscreenCanvas.transferToImageBitmap(); + // trasnform should be preserved + ctx.fillRect(0, 0, 10, 10); + var image2 = offscreenCanvas.transferToImageBitmap(); + + var drawCanvas = document.createElement('canvas'); + drawCanvas.width = 100; + drawCanvas.height = 50; + var dCtx = drawCanvas.getContext('2d'); + dCtx.drawImage(image2, 0, 0); + // Verify that transform was carried over. + _assertPixel(drawCanvas, 23,25, 0,255,0,255); + // Verify that clip was carried over. + _assertPixel(drawCanvas, 27,25, 0,0,0,0); +}, "Test that transferToImageBitmap preserves transform"); + +async_test(function(t) { + var worker = makeWorker(document.getElementById("myWorker").textContent); + var offscreenCanvas = new OffscreenCanvas(10, 10); + worker.postMessage(offscreenCanvas, [offscreenCanvas]); + assert_throws_dom("InvalidStateError", function() { offscreenCanvas.transferToImageBitmap(); }); + t.done(); +}, "Test that call transferToImageBitmap on a detached OffscreenCanvas throws an exception"); + +test(function() { + var offscreenCanvas = new OffscreenCanvas(10, 10); + assert_throws_dom("InvalidStateError", function() { offscreenCanvas.transferToImageBitmap(); }); +}, "Test that transferToImageBitmap without a context throws an exception"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.nocrash.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.nocrash.html new file mode 100644 index 0000000000..09a388ed35 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.nocrash.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<body> + <p>Tests that an ImageBitmap in Offscreen without content does not crash.</p> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +async_test(function(t) { + var v1 = document.createElement("canvas"); + var v2 = v1.transferControlToOffscreen(); + var v3 = v2.getContext("bitmaprenderer"); + v2.width = 67; + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html new file mode 100644 index 0000000000..b51ce0efa2 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html @@ -0,0 +1,201 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-transfertoimagebitmap"> + +<script id="myWorker" type="text/worker"> + +function testSize(contextType) +{ + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext(contextType); + var image = offscreenCanvas.transferToImageBitmap(); + if (image.width == 100 && image.height == 50) + return true; + return false; +} + +function testImageBitmapClr(shouldCallTwice, alphaVal) { + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d', {alpha: alphaVal}); + ctx.fillStyle = "#0f0"; + ctx.fillRect(0, 0, 100, 50); + var image = offscreenCanvas.transferToImageBitmap(); + + if (shouldCallTwice) + image = offscreenCanvas.transferToImageBitmap(); + return image; +} + +function isInvalidStateError(funcStr, offscreenCanvas) +{ + try { + eval(funcStr); + } catch (e) { + if (e instanceof DOMException && e.name == "InvalidStateError") + return true; + return false; + } +} + +function testImageBitmapSize() +{ + return testSize('2d') && testSize('webgl'); +} + +function testLineWidthNotAltered() +{ + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.lineWidth = 10; + var image = offscreenCanvas.transferToImageBitmap(); + return ctx.lineWidth == 10; +} + +function testTransformPreserved() +{ + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext('2d'); + ctx.rect(0, 0, 25, 50); + ctx.clip(); + ctx.translate(20, 20); + + ctx.fillStyle = '#0f0'; + var image1 = offscreenCanvas.transferToImageBitmap(); + // trasnform should be preserved + ctx.fillRect(0, 0, 10, 10); + var image2 = offscreenCanvas.transferToImageBitmap(); + return image2; +} + +function testException() +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + return isInvalidStateError("offscreenCanvas.transferToImageBitmap()", offscreenCanvas); +} + +self.onmessage = function(e) { + switch (e.data) { + case 'test1': + self.postMessage(testImageBitmapSize()); + break; + case 'test2': + self.postMessage(testImageBitmapClr(false, true)); + break; + case 'test3': + self.postMessage(testImageBitmapClr(true, true)); + break; + case 'test4': + self.postMessage(testImageBitmapClr(true, false)); + break; + case 'test5': + self.postMessage(testLineWidthNotAltered()); + break; + case 'test6': + self.postMessage(testTransformPreserved()); + break; + case 'test7': + var offscreenCanvas = new OffscreenCanvas(10, 10); + self.postMessage({offscreenCanvas: offscreenCanvas}, [offscreenCanvas]); + self.postMessage(isInvalidStateError("offscreenCanvas.transferToImageBitmap()", offscreenCanvas)); + break; + case 'test8': + self.postMessage(testException()); + break; + } +}; + +</script> + +<script> +function makeWorker(test) { + var blob = new Blob([document.getElementById("myWorker").textContent]); + var worker = new Worker(URL.createObjectURL(blob)); + worker.onerror = test.unreached_func("error"); + return worker; +} + +function drawImageBitmap(image, x, y) +{ + var drawCanvas = document.createElement('canvas'); + drawCanvas.width = 100; + drawCanvas.height = 50; + var dCtx = drawCanvas.getContext('2d'); + dCtx.drawImage(image, 0, 0); + return dCtx.getImageData(x, y, 1, 1).data; +} + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + })); + worker.postMessage('test1'); +}, "Test that transferToImageBitmap returns an ImageBitmap with correct width and height in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + var clr = drawImageBitmap(msg.data, 50, 25); + assert_array_equals(clr, [0, 255, 0, 255]); + })); + worker.postMessage('test2'); +}, "Test that transferToImageBitmap returns an ImageBitmap with correct color in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + var clr = drawImageBitmap(msg.data, 50, 25); + assert_array_equals(clr, [0, 0, 0, 0]); + })); + worker.postMessage('test3'); +}, "Test that call transferToImageBitmap twice returns an ImageBitmap with correct color in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + var clr = drawImageBitmap(msg.data, 50, 25); + assert_array_equals(clr, [0, 0, 0, 255]); + })); + worker.postMessage('test4'); +}, "Test that call transferToImageBitmap twice on a alpha-disabled context returns an ImageBitmap with correct color in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + })); + worker.postMessage('test5'); +}, "Test that transferToImageBitmap won't change context's property in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + var clr1 = drawImageBitmap(msg.data, 23, 25); + assert_array_equals(clr1, [0, 255, 0, 255]); + var clr2 = drawImageBitmap(msg.data, 27, 25); + assert_array_equals(clr2, [0, 0, 0, 0]); + })); + worker.postMessage('test6'); +}, "Test that call transferToImageBitmap preserves transform in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + if (msg.data == true || msg.data == false) + assert_true(msg.data); + })); + worker.postMessage('test7'); +}, "Test that call transferToImageBitmap on a detached OffscreenCanvas throws an exception in a worker"); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + })); + worker.postMessage('test8'); +}, "Test that call transferToImageBitmap without a context throws an exception in a worker"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.html new file mode 100644 index 0000000000..fea375b2ad --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-canvas-transfercontroltooffscreen"> +<script> + +test(function() { + var placeholder = document.createElement('canvas'); + placeholder.width = 100; + placeholder.height = 50; + var offscreenCanvas = placeholder.transferControlToOffscreen(); + assert_equals(offscreenCanvas.width, 100); + assert_equals(offscreenCanvas.height, 50); +}, "Test that an OffscreenCanvas generated by transferControlToOffscreen gets correct width and height"); + +test(function() { + var placeholder = document.createElement('canvas'); + placeholder.width = 100; + placeholder.height = 50; + var offscreenCanvas = placeholder.transferControlToOffscreen(); + assert_throws_dom("InvalidStateError", function() { placeholder.getContext('2d'); }); +}, "Test that calling getContext on a placeholder canvas that has already transferred its control throws an exception"); + +test(function() { + var placeholder = document.createElement('canvas'); + placeholder.width = 100; + placeholder.height = 50; + var offscreenCanvas = placeholder.transferControlToOffscreen(); + assert_throws_dom("InvalidStateError", function() { placeholder.transferControlToOffscreen(); }); +}, "Test that calling transferControlToOffscreen twice throws an exception"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w.html new file mode 100644 index 0000000000..1347e7b50b --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w.html @@ -0,0 +1,76 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#dom-canvas-transfercontroltooffscreen"> + +<script id="myWorker" type="text/worker"> + +function testSize(offscreenCanvas) +{ + if (offscreenCanvas.width == 100 && offscreenCanvas.height == 50) + return true; + return false; +} + +self.onmessage = function(e) { + switch (e.data.msg) { + case 'test1': + self.postMessage(testSize(e.data.data)); + break; + case 'test2': + self.postMessage(""); + break; + case 'test3': + self.postMessage(""); + break; + } +}; + +</script> + +<script> +function makeWorker(script) +{ + var blob = new Blob([script]); + return new Worker(URL.createObjectURL(blob)); +} + +async_test(function(t) { + var placeholder = document.createElement('canvas'); + placeholder.width = 100; + placeholder.height = 50; + var offscreenCanvas = placeholder.transferControlToOffscreen(); + var worker = makeWorker(document.getElementById("myWorker").textContent); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + })); + worker.postMessage({msg: 'test1', data: offscreenCanvas}, [offscreenCanvas]); +}, "Test that an OffscreenCanvas generated by transferControlToOffscreen gets correct width and height when it is transferred to a worker"); + +async_test(function(t) { + var placeholder = document.createElement('canvas'); + placeholder.width = 100; + placeholder.height = 50; + var offscreenCanvas = placeholder.transferControlToOffscreen(); + var worker = makeWorker(document.getElementById("myWorker").textContent); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_throws_dom("InvalidStateError", function() { placeholder.getContext('2d'); }); + })); + worker.postMessage({msg: 'test2', data: offscreenCanvas}, [offscreenCanvas]); +}, "Test that calling getContext on a placeholder canvas that is transferred its control to an OffscreenCanvas throws an exception, when the OffscreenCanvas is transferred to a worker"); + +async_test(function(t) { + var placeholder = document.createElement('canvas'); + placeholder.width = 100; + placeholder.height = 50; + var offscreenCanvas = placeholder.transferControlToOffscreen(); + var worker = makeWorker(document.getElementById("myWorker").textContent); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_throws_dom("InvalidStateError", function() { placeholder.transferControlToOffscreen(); }); + })); + worker.postMessage({msg: 'test3', data: offscreenCanvas}, [offscreenCanvas]); +}, "Test that calling transferControlToOffscreen twice throws an exception, when its associated OffscreenCanvas is transferred to a worker"); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.html new file mode 100644 index 0000000000..76796034e9 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#offscreencanvas"> + +<script id="myWorker" type="text/worker"> + +function test1(offscreenCanvas) +{ + return offscreenCanvas.width == 10 && offscreenCanvas.height == 10; +} + +self.onmessage = function(e) { + switch(e.data.msg) { + case 'test1': + self.postMessage(test1(e.data.data)); + break; + } +}; + +</script> + +<script> +function makeWorker(script) +{ + var blob = new Blob([script]); + return new Worker(URL.createObjectURL(blob)); +} + +async_test(function(t) { + var worker = makeWorker(document.getElementById("myWorker").textContent); + var offscreenCanvas = new OffscreenCanvas(10, 10); + worker.postMessage({msg: 'test1', data: offscreenCanvas}, [offscreenCanvas]); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + })); + assert_equals(offscreenCanvas.width, 0); + assert_equals(offscreenCanvas.height, 0); +}, "Test that offscreenCanvas's size is correct after being transferred to a worker."); + + +test(function() { + function testException(contextType) { + var worker = makeWorker(document.getElementById("myWorker").textContent); + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext(contextType); + assert_throws_dom("InvalidStateError", function() { + worker.postMessage({offscreenCanvas}, [offscreenCanvas]); + }); + } + testException('2d'); +}, "Test that transfer an OffscreenCanvas that already have a 2d context throws exception."); + +test(function() { + var worker = makeWorker(document.getElementById("myWorker").textContent); + var offscreenCanvas = new OffscreenCanvas(10, 10); + worker.postMessage({offscreenCanvas}, [offscreenCanvas]); + assert_throws_dom("DataCloneError", function() { + worker.postMessage({offscreenCanvas}, [offscreenCanvas]); + }); +}, "Test that transfer an OffscreenCanvas twice throws exception."); + +test(function() { + var worker = makeWorker(document.getElementById("myWorker").textContent); + var offscreenCanvas = new OffscreenCanvas(10, 10); + worker.postMessage({offscreenCanvas}, [offscreenCanvas]); + assert_throws_dom("InvalidStateError", function() { + offscreenCanvas.getContext('2d'); + }); +}, "Test that calling getContext('2d') on a detached OffscreenCanvas throws exception."); + +test(function() { + var worker = makeWorker(document.getElementById("myWorker").textContent); + var offscreenCanvas = new OffscreenCanvas(10, 10); + worker.postMessage({offscreenCanvas}, [offscreenCanvas]); + assert_throws_dom("InvalidStateError", function() { + offscreenCanvas.getContext('webgl'); + }); +}, "Test that calling getContext('webgl') on a detached OffscreenCanvas throws exception."); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html new file mode 100644 index 0000000000..38f981e8f0 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html @@ -0,0 +1,142 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/#offscreencanvas"> + +<script id="myWorker" type="text/worker"> + +function isInvalidStateError(funcStr, offscreenCanvas) +{ + try { + eval(funcStr); + } catch (e) { + if (e instanceof DOMException && e.name == "InvalidStateError") + return true; + return false; + } +} + +function testExceptionWith2DContext() +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('2d'); + return isInvalidStateError("self.postMessage(offscreenCanvas, [offscreenCanvas])", offscreenCanvas); +} + +function testExceptionWithWebGLContext() +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + var ctx = offscreenCanvas.getContext('webgl'); + return isInvalidStateError("self.postMessage(offscreenCanvas, [offscreenCanvas])", offscreenCanvas); +} + +function testExceptionWithDetachedOffscreenCanvas1() +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + self.postMessage(offscreenCanvas, [offscreenCanvas]); + return isInvalidStateError("self.postMessage(offscreenCanvas, [offscreenCanvas])", offscreenCanvas); +} + +function testExceptionWithDetachedOffscreenCanvas2() +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + self.postMessage(offscreenCanvas, [offscreenCanvas]); + return isInvalidStateError("offscreenCanvas.getContext('2d')", offscreenCanvas); +} + +function testExceptionWithDetachedOffscreenCanvas3() +{ + var offscreenCanvas = new OffscreenCanvas(10, 10); + self.postMessage(offscreenCanvas, [offscreenCanvas]); + return isInvalidStateError("offscreenCanvas.getContext('webgl')", offscreenCanvas); +} + +self.onmessage = function(e) { + switch(e.data) { + case 'test1': + var offscreenCanvas = new OffscreenCanvas(10, 10); + self.postMessage(offscreenCanvas, [offscreenCanvas]); + break; + case 'test2': + self.postMessage(testExceptionWith2DContext()); + break; + case 'test3': + self.postMessage(testExceptionWithWebGLContext()); + break; + case 'test4': + self.postMessage(testExceptionWithDetachedOffscreenCanvas1()); + break; + case 'test5': + self.postMessage(testExceptionWithDetachedOffscreenCanvas2()); + break; + case 'test6': + self.postMessage(testExceptionWithDetachedOffscreenCanvas3()); + break; + } +}; + +</script> + +<script> +function makeWorker(test) { + var blob = new Blob([document.getElementById("myWorker").textContent]); + var worker = new Worker(URL.createObjectURL(blob)); + worker.onerror = test.unreached_func("error"); + return worker; +} + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_equals(msg.data.width, 10); + assert_equals(msg.data.height, 10); + })); + worker.postMessage('test1'); +}, "Test that OffscreenCanvas's size is correct after being transferred from a worker."); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + })); + worker.postMessage('test2'); +}, "Test that transfer an OffscreenCanvas that has a 2d context throws exception in a worker."); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + assert_true(msg.data); + })); + worker.postMessage('test3'); +}, "Test that transfer an OffscreenCanvas that has a webgl context throws exception in a worker."); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + if (msg.data == true || msg.data == false) + assert_true(msg.data); + })); + worker.postMessage('test4'); +}, "Test that transfer an OffscreenCanvas twice throws exception in a worker."); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + if (msg.data == true || msg.data == false) + assert_true(msg.data); + })); + worker.postMessage('test5'); +}, "Test that calling getContext('2d') on a detached OffscreenCanvas throws exception in a worker."); + +async_test(function(t) { + var worker = makeWorker(t); + worker.addEventListener('message', t.step_func_done(function(msg) { + if (msg.data == true || msg.data == false) + assert_true(msg.data); + })); + worker.postMessage('test6'); +}, "Test that calling getContext('webgl') on a detached OffscreenCanvas throws exception in a worker."); + +</script> + diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/transformations/2d.transformation.getTransform.html b/testing/web-platform/tests/html/canvas/offscreen/manual/transformations/2d.transformation.getTransform.html new file mode 100644 index 0000000000..b3b70ac208 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/transformations/2d.transformation.getTransform.html @@ -0,0 +1,40 @@ +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +// Ensure that context2d.getTransform works +const epsilon = 1e-5; +const canvas = new OffscreenCanvas(300, 150); +const ctx = canvas.getContext('2d'); + +test(function(t) { + + assert_array_equals(ctx.getTransform().toFloat32Array(), + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], + "Assert that an untransformed matrix is identity"); + + ctx.scale(2, 3); + transform = ctx.getTransform(); + assert_array_equals(ctx.getTransform().toFloat32Array(), + [2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], + "Assert that context2d scaling works"); + + ctx.rotate(Math.PI/2); + transform = ctx.getTransform(); + assert_array_approx_equals(ctx.getTransform().toFloat32Array(), + [0, 3, 0, 0, -2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], epsilon, + "Assert that context2d rotate works"); + + ctx.translate(1, -1); + transform = ctx.getTransform(); + assert_array_approx_equals(ctx.getTransform().toFloat32Array(), + [0, 3, 0, 0, -2, 0, 0, 0, 0, 0, 1, 0, 2, 3, 0, 1], epsilon, + "Assert context2d translate works."); + + ctx.resetTransform(); + assert_array_equals(ctx.getTransform().toFloat32Array(), + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], + "Assert that a reset matrix is identity"); +}, 'This test ensures that getTransform works correctly.'); +</script> +</body> diff --git a/testing/web-platform/tests/html/canvas/offscreen/manual/wide-gamut-canvas/2d.color.space.p3.convertToBlobp3.canvas.html b/testing/web-platform/tests/html/canvas/offscreen/manual/wide-gamut-canvas/2d.color.space.p3.convertToBlobp3.canvas.html new file mode 100644 index 0000000000..9fc63a9f49 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/offscreen/manual/wide-gamut-canvas/2d.color.space.p3.convertToBlobp3.canvas.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<title>OffscreenCanvas test: 2d.color.space.p3.convertToBlob.p3.canvas</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/canvas/resources/canvas-tests.js"></script> + +<h1>2d.color.space.p3.convertToBlob.p3.canvas</h1> +<p class="desc">test if toblob returns p3 data from p3 color space canvas</p> + + +<script> +var t = async_test("test if toblob returns p3 data from p3 color space canvas"); +var t_pass = t.done.bind(t); +var t_fail = t.step_func(function(reason) { + throw reason; +}); +t.step(function() { + +var offscreenCanvas = new OffscreenCanvas(100, 50); +var ctx = offscreenCanvas.getContext('2d', {colorSpace: "display-p3"}); + +ctx.fillStyle = "rgba(155, 27, 27, 1)"; +ctx.fillRect(0, 0, 1, 1); +ctx.fillStyle = "rgba(27, 155, 27, 0)"; +ctx.fillRect(1, 0, 1, 1); +ctx.fillStyle = "rgba(27, 27, 155, 0.5)"; +ctx.fillRect(0, 1, 1, 1); +ctx.fillStyle = "rgba(27, 27, 27, 0.5)"; +ctx.fillRect(1, 1, 1, 1); +expectedPixels = ctx.getImageData(0, 0, 2, 2, {colorSpace: "display-p3"}).data; + +var image = new Image(); +image.onload = t.step_func_done(function() { + var dstCanvas = document.createElement("canvas"); + dstCanvas.width = 2; + dstCanvas.height = 2; + var ctx = dstCanvas.getContext('2d', {colorSpace: "display-p3"}); + ctx.drawImage(image, 0, 0); + var actualPixels = ctx.getImageData(0, 0, 2, 2, {colorSpace: "display-p3"}).data; + assert_array_approx_equals(actualPixels, expectedPixels, 2); +}); + +offscreenCanvas.convertToBlob(function(blob) { + var urlCreator = window.URL || window.webkitURL; + image.src = urlCreator.createObjectURL(blob); +}, 'image/png', 1); +t.done() + +}); +</script> |