diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/html/canvas/tools/yaml-new | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/canvas/tools/yaml-new')
9 files changed, 3122 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/color_space.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/color_space.yaml new file mode 100644 index 0000000000..ba5d93e0b0 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/color_space.yaml @@ -0,0 +1,329 @@ +- name: 2d.color.space.p3.to.p3 + desc: test getImageData with display-p3 and uint8 from display p3 uint8 canvas + attributes: | + {colorSpace: "display-p3"} + code: | + var color_style = 'rgb(50, 100, 150)'; + // [0.24304, 0.38818, 0.57227, 1.0] * 255 = [62, 99, 146, 255] + var pixel_expected = [62, 99, 146, 255]; + var epsilon = 2; + ctx.fillStyle = color_style; + ctx.fillRect(0, 0, 10, 10); + + var pixel = ctx.getImageData(5, 5, 1, 1, {colorSpace: "display-p3", storageFormat: "uint8"}).data; + @assert pixel.length === pixel_expected.length; + assert_approx_equals(pixel[0], pixel_expected[0], 2); + assert_approx_equals(pixel[1], pixel_expected[1], 2); + assert_approx_equals(pixel[2], pixel_expected[2], 2); + assert_approx_equals(pixel[3], pixel_expected[3], 2); + +- name: 2d.color.space.p3.to.srgb + desc: test getImageData with srsb and uint8 from display p3 uint8 canvas + attributes: | + {colorSpace: "display-p3"} + code: | + var color_style = 'rgb(50, 100, 150)'; + var pixel_expected = [50, 100, 150, 255]; + var epsilon = 2; + ctx.fillStyle = color_style; + ctx.fillRect(0, 0, 10, 10); + + var pixel = ctx.getImageData(5, 5, 1, 1, {colorSpace: "srgb", storageFormat: "uint8"}).data; + @assert pixel.length === pixel_expected.length; + assert_approx_equals(pixel[0], pixel_expected[0], 2); + assert_approx_equals(pixel[1], pixel_expected[1], 2); + assert_approx_equals(pixel[2], pixel_expected[2], 2); + assert_approx_equals(pixel[3], pixel_expected[3], 2); + +- name: 2d.color.space.p3.toBlob.p3.canvas + desc: test if toblob returns p3 data from p3 color space canvas + attributes: | + {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] + code: | + 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); + }); + + canvas.toBlob(function(blob) { + var urlCreator = window.URL || window.webkitURL; + image.src = urlCreator.createObjectURL(blob); + }, 'image/png', 1); + +- name: 2d.color.space.p3.toDataURL.p3.canvas + desc: test if toDataURL returns p3 data from canvas with p3 color space + attributes: | + {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] + code: | + 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); + }); + image.src = canvas.toDataURL(); + +- name: 2d.color.space.p3.toDataURL.jpeg.p3.canvas + desc: test if toDataURL('image/jpeg') returns p3 data from canvas with p3 color space + attributes: | + {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] + code: | + 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); + }); + image.src = canvas.toDataURL("image/jpeg"); + +- name: 2d.color.space.p3.toBlob.with.putImageData + desc: Use putImageData to put some p3 data in canvas and test if toBlob returns the same data + attributes: | + {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] + code: | + canvas.width = 2; + canvas.height = 2; + + // Create an ImageData using createImageData and populate its data array. + var image_data = ctx.createImageData(canvas.width, canvas.height, {colorSpace: "display-p3"}); + var color_data = [[255, 100, 150, 1.0], [255, 100, 150, 0.5], + [255, 100, 150, 0.5], [255, 100, 150, 0]]; + var data = image_data.data; + for (var i = 0; i < data.length / 4; ++i) { + data[4*i + 0] = color_data[i][0]; + data[4*i + 1] = color_data[i][1]; + data[4*i + 2] = color_data[i][2]; + data[4*i + 3] = color_data[i][3]; + } + ctx.putImageData(image_data, 0, 0); + 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); + }); + canvas.toBlob(function(blob) { + var urlCreator = window.URL || window.webkitURL; + image.src = urlCreator.createObjectURL(blob); + }, 'image/png', 1); + +- name: 2d.color.space.p3.toDataURL.with.putImageData + desc: Use putImageData to put some p3 data in canvas and test if toDataURL returns the same data + attributes: | + {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] + code: | + canvas.width = 2; + canvas.height = 2; + + // Create an ImageData using createImageData and populate its data array. + var image_data = ctx.createImageData(canvas.width, canvas.height, {colorSpace: "display-p3"}); + var color_data = [[255, 100, 150, 1.0], [255, 100, 150, 0.5], + [255, 100, 150, 0.5], [255, 100, 150, 0]]; + var data = image_data.data; + for (var i = 0; i < data.length / 4; ++i) { + data[4*i + 0] = color_data[i][0]; + data[4*i + 1] = color_data[i][1]; + data[4*i + 2] = color_data[i][2]; + data[4*i + 3] = color_data[i][3]; + } + ctx.putImageData(image_data, 0, 0); + 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); + }); + image.src = canvas.toDataURL(); + +- name: 2d.color.space.p3.fillText + desc: Test if fillText can be used with a solid display-p3 color + attributes: | + {colorSpace: "display-p3"} + canvasType: ['HTMLCanvas'] + code: | + deferTest(); + + const fullRedInP3 = [255, 0, 0, 255]; + const sRGBRedInP3 = [234, 51, 35, 255]; + + canvas.width = 100; + canvas.height = 100; + + let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)"); + document.fonts.add(f); + f.load().then(function() { + t.step(function() { + ctx.font = "40px Ahem"; + + ctx.fillStyle = "#f00"; + ctx.fillText("A", 0, 50); + + ctx.fillStyle = "black"; + ctx.fillStyle = "color(display-p3 100% 0 0)"; + ctx.fillText("A", 50, 50); + + let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data; + let pixelAt = function(x, y) { + let offset = (y * canvas.width + x) * 4; + return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]]; + }; + + assert_array_equals(pixelAt(25, 25), sRGBRedInP3); + assert_array_equals(pixelAt(75, 25), fullRedInP3); + + t.done(); + }); + }); + +- name: 2d.color.space.p3.strokeText + desc: Test if strokeText can be used with a solid display-p3 color + attributes: | + {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] + code: | + deferTest(); + + const fullRedInP3 = [255, 0, 0, 255]; + const sRGBRedInP3 = [234, 51, 35, 255]; + + canvas.width = 100; + canvas.height = 100; + + let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)"); + document.fonts.add(f); + f.load().then(function() { + t.step(function() { + ctx.font = "40px Ahem"; + + ctx.strokeStyle = "#f00"; + ctx.lineWidth = 20; + ctx.strokeText("A", 0, 50); + + ctx.strokeStyle = "black"; + ctx.strokeStyle = "color(display-p3 100% 0 0)"; + ctx.strokeText("A", 50, 50); + + let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data; + let pixelAt = function(x, y) { + let offset = (y * canvas.width + x) * 4; + return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]]; + }; + + assert_array_equals(pixelAt(25, 25), sRGBRedInP3); + assert_array_equals(pixelAt(75, 25), fullRedInP3); + + t.done(); + }); + }); + +- name: 2d.color.space.p3.fillText.shadow + desc: Test if fillText can be used with a display-p3 shadow color + attributes: | + {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] + code: | + deferTest(); + + const fullRedInP3 = [255, 0, 0, 255]; + const sRGBRedInP3 = [234, 51, 35, 255]; + + canvas.width = 100; + canvas.height = 100; + + let f = new FontFace("Ahem", "url(/fonts/Ahem.ttf)"); + document.fonts.add(f); + f.load().then(function() { + t.step(function() { + ctx.font = "40px Ahem"; + + ctx.fillStyle = "black"; + ctx.shadowBlur = 4; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 50; + ctx.shadowColor = "#f00"; + ctx.fillText("A", 0, 0); + + ctx.shadowColor = "black"; + ctx.shadowColor = "color(display-p3 100% 0 0)"; + ctx.fillText("A", 50, 0); + + let pixels = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: "display-p3" }).data; + let pixelAt = function(x, y) { + let offset = (y * canvas.width + x) * 4; + return [pixels[offset], pixels[offset + 1], pixels[offset + 2], pixels[offset + 3]]; + }; + + assert_array_equals(pixelAt(25, 25), sRGBRedInP3); + assert_array_equals(pixelAt(75, 25), fullRedInP3); + + t.done(); + }); + }); diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/compositing.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/compositing.yaml new file mode 100644 index 0000000000..c0b7b83e00 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/compositing.yaml @@ -0,0 +1,262 @@ +- name: 2d.composite.globalAlpha.range + code: | + ctx.globalAlpha = 0.5; + var a = ctx.globalAlpha; // might not be exactly 0.5, if it is rounded/quantised, so remember for future comparisons + ctx.globalAlpha = 1.1; + @assert ctx.globalAlpha === a; + ctx.globalAlpha = -0.1; + @assert ctx.globalAlpha === a; + ctx.globalAlpha = 0; + @assert ctx.globalAlpha === 0; + ctx.globalAlpha = 1; + @assert ctx.globalAlpha === 1; + +- name: 2d.composite.globalAlpha.invalid + code: | + ctx.globalAlpha = 0.5; + var a = ctx.globalAlpha; // might not be exactly 0.5, if it is rounded/quantised, so remember for future comparisons + ctx.globalAlpha = Infinity; + @assert ctx.globalAlpha === a; + ctx.globalAlpha = -Infinity; + @assert ctx.globalAlpha === a; + ctx.globalAlpha = NaN; + @assert ctx.globalAlpha === a; + +- name: 2d.composite.globalAlpha.default + code: | + @assert ctx.globalAlpha === 1.0; + +- name: 2d.composite.globalAlpha.fill + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 ==~ 2,253,0,255; + expected: green + +- name: 2d.composite.globalAlpha.image + images: + - red.png + canvasType: + ['HTMLCanvas'] + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.drawImage(document.getElementById('red.png'), 0, 0); + @assert pixel 50,25 ==~ 2,253,0,255; + expected: green + +- name: 2d.composite.globalAlpha.canvas + canvasType: ['HTMLCanvas'] + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 100; + canvas2.height = 50; + var ctx2 = canvas2.getContext('2d'); + ctx2.fillStyle = '#f00'; + ctx2.fillRect(0, 0, 100, 50); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.drawImage(canvas2, 0, 0); + @assert pixel 50,25 ==~ 2,253,0,255; + expected: green + +- name: 2d.composite.globalAlpha.imagepattern + images: + - red.png + canvasType: ['HTMLCanvas'] + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = ctx.createPattern(document.getElementById('red.png'), 'no-repeat'); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 ==~ 2,253,0,255; + expected: green + +- name: 2d.composite.globalAlpha.canvaspattern + canvasType: ['HTMLCanvas'] + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 100; + canvas2.height = 50; + var ctx2 = canvas2.getContext('2d'); + ctx2.fillStyle = '#f00'; + ctx2.fillRect(0, 0, 100, 50); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = ctx.createPattern(canvas2, 'no-repeat'); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 ==~ 2,253,0,255; + expected: green + +- name: 2d.composite.globalAlpha.canvascopy + canvasType: ['HTMLCanvas'] + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 100; + canvas2.height = 50; + var ctx2 = canvas2.getContext('2d'); + ctx2.fillStyle = '#0f0'; + ctx2.fillRect(0, 0, 100, 50); + + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + + ctx.globalCompositeOperation = 'copy' + ctx.globalAlpha = 0.51; + ctx.drawImage(canvas2, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,130; + expected: green + + +- name: 2d.composite.operation.get + code: | + var modes = ['source-atop', 'source-in', 'source-out', 'source-over', + 'destination-atop', 'destination-in', 'destination-out', 'destination-over', + 'lighter', 'copy', 'xor']; + for (var i = 0; i < modes.length; ++i) + { + ctx.globalCompositeOperation = modes[i]; + @assert ctx.globalCompositeOperation === modes[i]; + } + +- name: 2d.composite.operation.unrecognised + code: | + ctx.globalCompositeOperation = 'xor'; + ctx.globalCompositeOperation = 'nonexistent'; + @assert ctx.globalCompositeOperation === 'xor'; + +- name: 2d.composite.operation.darker + code: | + ctx.globalCompositeOperation = 'xor'; + ctx.globalCompositeOperation = 'darker'; + @assert ctx.globalCompositeOperation === 'xor'; + +- name: 2d.composite.operation.over + code: | + ctx.globalCompositeOperation = 'xor'; + ctx.globalCompositeOperation = 'over'; + @assert ctx.globalCompositeOperation === 'xor'; + +- name: 2d.composite.operation.clear + code: | + ctx.globalCompositeOperation = 'xor'; + ctx.globalCompositeOperation = 'clear'; + @assert ctx.globalCompositeOperation === 'clear'; + +- name: 2d.composite.operation.highlight + code: | + ctx.globalCompositeOperation = 'xor'; + ctx.globalCompositeOperation = 'highlight'; + @assert ctx.globalCompositeOperation === 'xor'; + +- name: 2d.composite.operation.nullsuffix + code: | + ctx.globalCompositeOperation = 'xor'; + ctx.globalCompositeOperation = 'source-over\0'; + @assert ctx.globalCompositeOperation === 'xor'; + +- name: 2d.composite.operation.casesensitive + code: | + ctx.globalCompositeOperation = 'xor'; + ctx.globalCompositeOperation = 'Source-over'; + @assert ctx.globalCompositeOperation === 'xor'; + +- name: 2d.composite.operation.default + code: | + @assert ctx.globalCompositeOperation === 'source-over'; + + +- name: 2d.composite.globalAlpha.image + canvasType: ['OffscreenCanvas'] + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 2,253,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.composite.globalAlpha.canvas + canvasType: ['OffscreenCanvas'] + code: | + var offscreenCanvas2 = new OffscreenCanvas(100, 50); + var ctx2 = offscreenCanvas2.getContext('2d'); + ctx2.fillStyle = '#f00'; + ctx2.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.drawImage(offscreenCanvas2, 0, 0); + @assert pixel 50,25 ==~ 2,253,0,255; + +- name: 2d.composite.globalAlpha.imagepattern + canvasType: ['OffscreenCanvas'] + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.fillStyle = ctx.createPattern(bitmap, 'no-repeat'); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 ==~ 2,253,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.composite.globalAlpha.canvaspattern + canvasType: ['OffscreenCanvas'] + code: | + var offscreenCanvas2 = new OffscreenCanvas(100, 50); + var ctx2 = offscreenCanvas2.getContext('2d'); + ctx2.fillStyle = '#f00'; + ctx2.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = ctx.createPattern(offscreenCanvas2, 'no-repeat'); + ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 ==~ 2,253,0,255; + +- name: 2d.composite.globalAlpha.canvascopy + canvasType: ['OffscreenCanvas'] + code: | + var offscreenCanvas2 = new OffscreenCanvas(100, 50); + var ctx2 = offscreenCanvas2.getContext('2d'); + ctx2.fillStyle = '#0f0'; + ctx2.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalCompositeOperation = 'copy' + ctx.globalAlpha = 0.51; + ctx.drawImage(offscreenCanvas2, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,130; diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/conformance_requirements.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/conformance_requirements.yaml new file mode 100644 index 0000000000..3483d115f4 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/conformance_requirements.yaml @@ -0,0 +1,178 @@ +- name: 2d.conformance.requirements.delete + desc: window.CanvasRenderingContext2D is Configurable + notes: &bindings Defined in "Web IDL" (draft) + canvasType: ['HTMLCanvas'] + code: | + @assert window.CanvasRenderingContext2D !== undefined; + @assert delete window.CanvasRenderingContext2D === true; + @assert window.CanvasRenderingContext2D === undefined; + +- name: 2d.conformance.requirements.basics + desc: void methods return undefined + notes: *bindings + code: | + @assert ctx.save() === undefined; + @assert ctx.restore() === undefined; + @assert ctx.scale(1, 1) === undefined; + @assert ctx.rotate(0) === undefined; + @assert ctx.translate(0, 0) === undefined; + if (ctx.transform) { // (avoid spurious failures, since the aim here is not to test that all features are supported) + @assert ctx.transform(1, 0, 0, 1, 0, 0) === undefined; + } + if (ctx.setTransform) { + @assert ctx.setTransform(1, 0, 0, 1, 0, 0) === undefined; + @assert ctx.setTransform() === undefined; + } + @assert ctx.clearRect(0, 0, 0, 0) === undefined; + @assert ctx.fillRect(0, 0, 0, 0) === undefined; + @assert ctx.strokeRect(0, 0, 0, 0) === undefined; + @assert ctx.beginPath() === undefined; + @assert ctx.closePath() === undefined; + @assert ctx.moveTo(0, 0) === undefined; + @assert ctx.lineTo(0, 0) === undefined; + @assert ctx.quadraticCurveTo(0, 0, 0, 0) === undefined; + @assert ctx.bezierCurveTo(0, 0, 0, 0, 0, 0) === undefined; + @assert ctx.arcTo(0, 0, 0, 0, 1) === undefined; + @assert ctx.rect(0, 0, 0, 0) === undefined; + @assert ctx.arc(0, 0, 1, 0, 0, true) === undefined; + @assert ctx.fill() === undefined; + @assert ctx.stroke() === undefined; + @assert ctx.clip() === undefined; + if (ctx.fillText) { + @assert ctx.fillText('test', 0, 0) === undefined; + @assert ctx.strokeText('test', 0, 0) === undefined; + } + if (ctx.putImageData) { + @assert ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined; + } + @assert ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined; + @assert ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined; + +- name: 2d.conformance.requirements.missingargs + desc: Missing arguments cause TypeError + code: | + @assert throws TypeError ctx.scale(); + @assert throws TypeError ctx.scale(1); + @assert throws TypeError ctx.rotate(); + @assert throws TypeError ctx.translate(); + @assert throws TypeError ctx.translate(0); + if (ctx.transform) { // (avoid spurious failures, since the aim here is not to test that all features are supported) + @assert throws TypeError ctx.transform(); + @assert throws TypeError ctx.transform(1); + @assert throws TypeError ctx.transform(1, 0); + @assert throws TypeError ctx.transform(1, 0, 0); + @assert throws TypeError ctx.transform(1, 0, 0, 1); + @assert throws TypeError ctx.transform(1, 0, 0, 1, 0); + } + if (ctx.setTransform) { + @assert throws TypeError ctx.setTransform(1); + @assert throws TypeError ctx.setTransform(1, 0); + @assert throws TypeError ctx.setTransform(1, 0, 0); + @assert throws TypeError ctx.setTransform(1, 0, 0, 1); + @assert throws TypeError ctx.setTransform(1, 0, 0, 1, 0); + } + @assert throws TypeError ctx.createLinearGradient(); + @assert throws TypeError ctx.createLinearGradient(0); + @assert throws TypeError ctx.createLinearGradient(0, 0); + @assert throws TypeError ctx.createLinearGradient(0, 0, 1); + @assert throws TypeError ctx.createRadialGradient(); + @assert throws TypeError ctx.createRadialGradient(0); + @assert throws TypeError ctx.createRadialGradient(0, 0); + @assert throws TypeError ctx.createRadialGradient(0, 0, 1); + @assert throws TypeError ctx.createRadialGradient(0, 0, 1, 0); + @assert throws TypeError ctx.createRadialGradient(0, 0, 1, 0, 0); + @assert throws TypeError ctx.createPattern(canvas); + @assert throws TypeError ctx.clearRect(); + @assert throws TypeError ctx.clearRect(0); + @assert throws TypeError ctx.clearRect(0, 0); + @assert throws TypeError ctx.clearRect(0, 0, 0); + @assert throws TypeError ctx.fillRect(); + @assert throws TypeError ctx.fillRect(0); + @assert throws TypeError ctx.fillRect(0, 0); + @assert throws TypeError ctx.fillRect(0, 0, 0); + @assert throws TypeError ctx.strokeRect(); + @assert throws TypeError ctx.strokeRect(0); + @assert throws TypeError ctx.strokeRect(0, 0); + @assert throws TypeError ctx.strokeRect(0, 0, 0); + @assert throws TypeError ctx.moveTo(); + @assert throws TypeError ctx.moveTo(0); + @assert throws TypeError ctx.lineTo(); + @assert throws TypeError ctx.lineTo(0); + @assert throws TypeError ctx.quadraticCurveTo(); + @assert throws TypeError ctx.quadraticCurveTo(0); + @assert throws TypeError ctx.quadraticCurveTo(0, 0); + @assert throws TypeError ctx.quadraticCurveTo(0, 0, 0); + @assert throws TypeError ctx.bezierCurveTo(); + @assert throws TypeError ctx.bezierCurveTo(0); + @assert throws TypeError ctx.bezierCurveTo(0, 0); + @assert throws TypeError ctx.bezierCurveTo(0, 0, 0); + @assert throws TypeError ctx.bezierCurveTo(0, 0, 0, 0); + @assert throws TypeError ctx.bezierCurveTo(0, 0, 0, 0, 0); + @assert throws TypeError ctx.arcTo(); + @assert throws TypeError ctx.arcTo(0); + @assert throws TypeError ctx.arcTo(0, 0); + @assert throws TypeError ctx.arcTo(0, 0, 0); + @assert throws TypeError ctx.arcTo(0, 0, 0, 0); + @assert throws TypeError ctx.rect(); + @assert throws TypeError ctx.rect(0); + @assert throws TypeError ctx.rect(0, 0); + @assert throws TypeError ctx.rect(0, 0, 0); + @assert throws TypeError ctx.arc(); + @assert throws TypeError ctx.arc(0); + @assert throws TypeError ctx.arc(0, 0); + @assert throws TypeError ctx.arc(0, 0, 1); + @assert throws TypeError ctx.arc(0, 0, 1, 0); + // (6th argument to arc is optional) + if (ctx.isPointInPath) { + @assert throws TypeError ctx.isPointInPath(); + @assert throws TypeError ctx.isPointInPath(0); + } + if (ctx.drawFocusRing) { + @assert throws TypeError ctx.drawFocusRing(); + @assert throws TypeError ctx.drawFocusRing(canvas); + @assert throws TypeError ctx.drawFocusRing(canvas, 0); + } + if (ctx.fillText) { + @assert throws TypeError ctx.fillText(); + @assert throws TypeError ctx.fillText('test'); + @assert throws TypeError ctx.fillText('test', 0); + @assert throws TypeError ctx.strokeText(); + @assert throws TypeError ctx.strokeText('test'); + @assert throws TypeError ctx.strokeText('test', 0); + @assert throws TypeError ctx.measureText(); + } + @assert throws TypeError ctx.drawImage(); + @assert throws TypeError ctx.drawImage(canvas); + @assert throws TypeError ctx.drawImage(canvas, 0); + // TODO: n >= 3 args on drawImage could be either a valid overload, + // or too few for another overload, or too many for another + // overload - what should happen? + if (ctx.createImageData) { + @assert throws TypeError ctx.createImageData(); + @assert throws TypeError ctx.createImageData(1); + } + if (ctx.getImageData) { + @assert throws TypeError ctx.getImageData(); + @assert throws TypeError ctx.getImageData(0); + @assert throws TypeError ctx.getImageData(0, 0); + @assert throws TypeError ctx.getImageData(0, 0, 1); + } + if (ctx.putImageData) { + var imgdata = ctx.getImageData(0, 0, 1, 1); + @assert throws TypeError ctx.putImageData(); + @assert throws TypeError ctx.putImageData(imgdata); + @assert throws TypeError ctx.putImageData(imgdata, 0); + } + var g = ctx.createLinearGradient(0, 0, 0, 0); + @assert throws TypeError g.addColorStop(); @moz-todo + @assert throws TypeError g.addColorStop(0); @moz-todo + + +- name: 2d.conformance.requirements.drawings + desc: void methods return undefined + images: + - yellow.png + canvasType: ['HTMLCanvas'] + code: | + @assert ctx.drawImage(document.getElementById('yellow.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined; + diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml new file mode 100644 index 0000000000..83de88113f --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml @@ -0,0 +1,1333 @@ +- name: 2d.drawImage.3arg + canvasType: ['HTMLCanvas'] + images: + - red.png + - green.png + code: | + ctx.drawImage(document.getElementById('green.png'), 0, 0); + ctx.drawImage(document.getElementById('red.png'), -100, 0); + ctx.drawImage(document.getElementById('red.png'), 100, 0); + ctx.drawImage(document.getElementById('red.png'), 0, -50); + ctx.drawImage(document.getElementById('red.png'), 0, 50); + + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.5arg + canvasType: ['HTMLCanvas'] + images: + - red.png + - green.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('green.png'), 50, 0, 50, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 50, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 50, 50); + + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.9arg.basic + canvasType: ['HTMLCanvas'] + images: + - green.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.9arg.sourcepos + canvasType: ['HTMLCanvas'] + images: + - rgrg-256x256.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('rgrg-256x256.png'), 140, 20, 100, 50, 0, 0, 100, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.9arg.sourcesize + canvasType: ['HTMLCanvas'] + images: + - rgrg-256x256.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('rgrg-256x256.png'), 0, 0, 256, 256, 0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 51, 26); + ctx.fillRect(49, 24, 51, 26); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + @assert pixel 20,20 ==~ 0,255,0,255; + @assert pixel 80,20 ==~ 0,255,0,255; + @assert pixel 20,30 ==~ 0,255,0,255; + @assert pixel 80,30 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.9arg.destpos + canvasType: ['HTMLCanvas'] + images: + - red.png + - green.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -100, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -50, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.9arg.destsize + canvasType: ['HTMLCanvas'] + images: + - red.png + - green.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('green.png'), 1, 1, 1, 1, 0, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -50, 0, 50, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 50, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -25, 100, 25); + ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 25); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.canvas + canvasType: ['HTMLCanvas'] + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 100; + canvas2.height = 50; + var ctx2 = canvas2.getContext('2d'); + ctx2.fillStyle = '#0f0'; + ctx2.fillRect(0, 0, 100, 50); + + ctx.fillStyle = '#f00'; + ctx.drawImage(canvas2, 0, 0); + + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + + ctx.drawImage(document.createElement('canvas'), 0, 0); + + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.self.1 + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 50, 50); + ctx.fillStyle = '#f00'; + ctx.fillRect(50, 0, 50, 50); + ctx.drawImage(canvas, 50, 0); + + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.self.2 + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 1, 100, 49); + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 1); + ctx.drawImage(canvas, 0, 1); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 2); + + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.null + code: | + @assert throws TypeError ctx.drawImage(null, 0, 0); + +- name: 2d.drawImage.wrongtype + desc: Incorrect image types in drawImage do not match any defined overloads, so + WebIDL throws a TypeError + code: | + @assert throws TypeError ctx.drawImage(undefined, 0, 0); + @assert throws TypeError ctx.drawImage(0, 0, 0); + @assert throws TypeError ctx.drawImage("", 0, 0); + +- name: 2d.drawImage.wrongtype.paragraph + desc: Incorrect image types in drawImage do not match any defined overloads, so + WebIDL throws a TypeError + notes: &bindings Defined in "Web IDL" (draft) + canvasType: ['HTMLCanvas'] + code: | + @assert throws TypeError ctx.drawImage(document.createElement('p'), 0, 0); + +- name: 2d.drawImage.floatsource + canvasType: ['HTMLCanvas'] + images: + - green.png + code: | + ctx.drawImage(document.getElementById('green.png'), 10.1, 10.1, 0.1, 0.1, 0, 0, 100, 50); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.zerosource + desc: drawImage with zero-sized source rectangle draws nothing without exception + canvasType: ['HTMLCanvas'] + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 10, 10, 0, 1, 0, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 10, 10, 1, 0, 0, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 10, 10, 0, 0, 0, 0, 100, 50); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.zerosource.image + desc: drawImage with zero-sized source rectangle from image draws nothing without exception + canvasType: ['HTMLCanvas'] + images: + - red-zerowidth.svg + - red-zeroheight.svg + - red-zerosize.svg + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('red-zerowidth.svg'), 0, 0, 100, 50); + ctx.drawImage(document.getElementById('red-zeroheight.svg'), 0, 0, 100, 50); + ctx.drawImage(document.getElementById('red-zerosize.svg'), 0, 0, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.drawImage.negativesource + desc: Negative source width/height represents the correct rectangle + canvasType: ['HTMLCanvas'] + mozilla: {throws: !!null ''} + images: + - ggrr-256x256.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 78, -100, 50, 0, 0, 50, 50); + ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 128, -100, -50, 50, 0, 50, 50); + @assert pixel 1,1 ==~ 0,255,0,255; + @assert pixel 1,48 ==~ 0,255,0,255; + @assert pixel 98,1 ==~ 0,255,0,255; + @assert pixel 98,48 ==~ 0,255,0,255; + @assert pixel 48,1 ==~ 0,255,0,255; + @assert pixel 48,48 ==~ 0,255,0,255; + @assert pixel 51,1 ==~ 0,255,0,255; + @assert pixel 51,48 ==~ 0,255,0,255; + @assert pixel 25,25 ==~ 0,255,0,255; + @assert pixel 75,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.negativedest + desc: Negative destination width/height represents the correct rectangle + canvasType: ['HTMLCanvas'] + mozilla: {throws: !!null ''} + images: + - ggrr-256x256.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 78, 50, 50, 0, 50, 50, -50); + ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 128, 50, -50, 100, 50, -50, -50); + @assert pixel 1,1 ==~ 0,255,0,255; + @assert pixel 1,48 ==~ 0,255,0,255; + @assert pixel 98,1 ==~ 0,255,0,255; + @assert pixel 98,48 ==~ 0,255,0,255; + @assert pixel 48,1 ==~ 0,255,0,255; + @assert pixel 48,48 ==~ 0,255,0,255; + @assert pixel 51,1 ==~ 0,255,0,255; + @assert pixel 51,48 ==~ 0,255,0,255; + @assert pixel 25,25 ==~ 0,255,0,255; + @assert pixel 75,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.negativedir + desc: Negative dimensions do not affect the direction of the image + canvasType: ['HTMLCanvas'] + mozilla: {throws: !!null ''} + images: + - ggrr-256x256.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('ggrr-256x256.png'), 0, 178, 50, -100, 0, 0, 50, 100); + ctx.drawImage(document.getElementById('ggrr-256x256.png'), 0, 78, 50, 100, 50, 100, 50, -100); + @assert pixel 1,1 ==~ 0,255,0,255; + @assert pixel 1,48 ==~ 0,255,0,255; + @assert pixel 98,1 ==~ 0,255,0,255; + @assert pixel 98,48 ==~ 0,255,0,255; + @assert pixel 48,1 ==~ 0,255,0,255; + @assert pixel 48,48 ==~ 0,255,0,255; + @assert pixel 51,1 ==~ 0,255,0,255; + @assert pixel 51,48 ==~ 0,255,0,255; + @assert pixel 25,25 ==~ 0,255,0,255; + @assert pixel 75,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.outsidesource + DISABLED: fix this to match the current spec (transparent black outside source) + canvasType: ['HTMLCanvas'] + mozilla: {throws: !!null ''} + images: + - green.png + - red.png + code: | + ctx.drawImage(document.getElementById('green.png'), 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50); + ctx.drawImage(document.getElementById('green.png'), 5.5, 5.5, -5.5, -5.5, 0, 0, 100, 50); + ctx.drawImage(document.getElementById('green.png'), 100, 50, -5, -5, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), -0.001, 0, 100, 50, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, -0.001, 100, 50, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, 100.001, 50, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50.001, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 50, 0, 50.001, 50, 0, 0, 100, 50); @moz-todo + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, -5, 5, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, 5, -5, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 110, 60, -20, -20, 0, 0, 100, 50); + @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo + expected: green + +- name: 2d.drawImage.incomplete.nosrc + canvasType: ['HTMLCanvas'] + mozilla: {throws: !!null ''} + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var img = new Image(); + ctx.drawImage(img, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.incomplete.immediate + canvasType: ['HTMLCanvas'] + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var img = new Image(); + img.src = '../images/red.png'; + // This triggers the "update the image data" algorithm. + // The image will not go to the "completely available" state + // until a fetch task in the networking task source is processed, + // so the image must not be fully decodable yet: + ctx.drawImage(img, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo + expected: green + +- name: 2d.drawImage.incomplete.reload + canvasType: ['HTMLCanvas'] + images: + - yellow.png + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var img = document.getElementById('yellow.png'); + img.src = '../images/red.png'; + // This triggers the "update the image data" algorithm, + // and resets the image to the "unavailable" state. + // The image will not go to the "completely available" state + // until a fetch task in the networking task source is processed, + // so the image must not be fully decodable yet: + ctx.drawImage(img, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo + expected: green + +- name: 2d.drawImage.incomplete.emptysrc + canvasType: ['HTMLCanvas'] + images: + - red.png + mozilla: {throws: !!null ''} + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var img = document.getElementById('red.png'); + img.src = ""; + ctx.drawImage(img, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.incomplete.removedsrc + canvasType: ['HTMLCanvas'] + images: + - red.png + mozilla: {throws: !!null ''} + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var img = document.getElementById('red.png'); + img.removeAttribute('src'); + ctx.drawImage(img, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.broken + canvasType: ['HTMLCanvas'] + images: + - broken.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var img = document.getElementById('broken.png'); + @assert throws INVALID_STATE_ERR ctx.drawImage(img, 0, 0); + expected: green + +- name: 2d.drawImage.nonexistent + canvasType: ['HTMLCanvas'] + images: + - not-found-at-all.png + code: | + var img = document.getElementById('not-found-at-all.png'); + @assert throws INVALID_STATE_ERR ctx.drawImage(img, 0, 0); + +- name: 2d.drawImage.zerocanvas + desc: drawImage with zero-sized canvas as the source shoud throw exception + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 0; + canvas2.height = 50; + @assert throws INVALID_STATE_ERR ctx.drawImage(canvas2, 0, 0); + + canvas2.width = 50; + canvas2.height = 0; + @assert throws INVALID_STATE_ERR ctx.drawImage(canvas2, 0, 0); + + canvas2.width = 0; + canvas2.height = 0; + @assert throws INVALID_STATE_ERR ctx.drawImage(canvas2, 0, 0); + +- name: 2d.drawImage.svg + desc: drawImage() of an SVG image + canvasType: ['HTMLCanvas'] + images: + - green.svg + code: | + ctx.drawImage(document.getElementById('green.svg'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.animated.gif + desc: drawImage() of an animated GIF draws the first frame + canvasType: ['HTMLCanvas'] + images: + - anim-gr.gif + code: | + deferTest(); + step_timeout(t.step_func_done(function () { + ctx.drawImage(document.getElementById('anim-gr.gif'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + }), 500); + expected: green + +- name: 2d.drawImage.animated.apng + desc: drawImage() of an APNG with no poster frame draws the first frame + canvasType: ['HTMLCanvas'] + images: + - anim-gr.png + code: | + deferTest(); + step_timeout(t.step_func_done(function () { + ctx.drawImage(document.getElementById('anim-gr.png'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + }), 500); + expected: green + +- name: 2d.drawImage.animated.poster + desc: drawImage() of an APNG draws the poster frame + canvasType: ['HTMLCanvas'] + images: + - anim-poster-gr.png + code: | + ctx.drawImage(document.getElementById('anim-poster-gr.png'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo + expected: green + +- name: 2d.drawImage.path + canvasType: ['HTMLCanvas'] + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.rect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('red.png'), 0, 0); + ctx.fill(); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.transform + canvasType: ['HTMLCanvas'] + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.translate(100, 0); + ctx.drawImage(document.getElementById('red.png'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +# TODO: drawImage shadows + +- name: 2d.drawImage.alpha + canvasType: ['HTMLCanvas'] + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0; + ctx.drawImage(document.getElementById('red.png'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.clip + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.rect(-10, -10, 1, 1); + ctx.clip(); + ctx.drawImage(document.getElementById('red.png'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.composite + canvasType: ['HTMLCanvas'] + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalCompositeOperation = 'destination-over'; + ctx.drawImage(document.getElementById('red.png'), 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.nowrap + desc: Stretched images do not get pixels wrapping around the edges + canvasType: ['HTMLCanvas'] + images: + - redtransparent.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(document.getElementById('redtransparent.png'), -1950, 0, 2000, 50); + @assert pixel 45,25 ==~ 0,255,0,255; + @assert pixel 50,25 ==~ 0,255,0,255; + @assert pixel 55,25 ==~ 0,255,0,255; + expected: green + +- name: 2d.drawImage.nonfinite + desc: drawImage() with Infinity/NaN is ignored + canvasType: ['HTMLCanvas'] + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var red = document.getElementById('red.png'); + @nonfinite ctx.drawImage(<red>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>); + @nonfinite ctx.drawImage(<red>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); + @nonfinite ctx.drawImage(<red>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.drawImage.3arg + canvasType: ['OffscreenCanvas'] + timeout: long + images: + - red.png + - green.png + code: | + var promise1 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + var promise2 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + Promise.all([promise1, promise2]).then(function(response1, response2) { + var promise3 = createImageBitmap(response1); + var promise4 = createImageBitmap(response2); + Promise.all([promise3, promise4]).then(function(bitmap1, bitmap2) { + ctx.drawImage(bitmap2, 0, 0); + ctx.drawImage(bitmap1, -100, 0); + ctx.drawImage(bitmap1, 100, 0); + ctx.drawImage(bitmap1, 0, -50); + ctx.drawImage(bitmap1, 0, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.5arg + images: + - red.png + - green.png + canvasType: ['OffscreenCanvas'] + timeout: long + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise1 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + var promise2 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + Promise.all([promise1, promise2]).then(function(response1, response2) { + var promise3 = createImageBitmap(response1); + var promise4 = createImageBitmap(response2); + Promise.all([promise3, promise4]).then(function(bitmap1, bitmap2) { + ctx.drawImage(bitmap2, 50, 0, 50, 50); + ctx.drawImage(bitmap1, 0, 0, 50, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 50, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.9arg.basic + canvasType: ['OffscreenCanvas'] + images: + - green.png + timeout: long + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0, 100, 50, 0, 0, 100, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.9arg.sourcepos + canvasType: ['OffscreenCanvas'] + images: + - rgrg-256x256.png + timeout: long + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/rgrg-256x256.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 140, 20, 100, 50, 0, 0, 100, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.9arg.sourcesize + canvasType: ['OffscreenCanvas'] + images: + - rgrg-256x256.png + timeout: long + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/rgrg-256x256.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0, 256, 256, 0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 51, 26); + ctx.fillRect(49, 24, 51, 26); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + @assert pixel 20,20 ==~ 0,255,0,255; + @assert pixel 80,20 ==~ 0,255,0,255; + @assert pixel 20,30 ==~ 0,255,0,255; + @assert pixel 80,30 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.9arg.destpos + canvasType: ['OffscreenCanvas'] + images: + - red.png + - green.png + timeout: long + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise1 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + var promise2 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + Promise.all([promise1, promise2]).then(function(response1, response2) { + var promise3 = createImageBitmap(response1); + var promise4 = createImageBitmap(response2); + Promise.all([promise3, promise4]).then(function(bitmap1, bitmap2) { + ctx.drawImage(bitmap2, 0, 0, 100, 50, 0, 0, 100, 50); + ctx.drawImage(bitmap1, 0, 0, 100, 50, -100, 0, 100, 50); + ctx.drawImage(bitmap1, 0, 0, 100, 50, 100, 0, 100, 50); + ctx.drawImage(bitmap1, 0, 0, 100, 50, 0, -50, 100, 50); + ctx.drawImage(bitmap1, 0, 0, 100, 50, 0, 50, 100, 50); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.9arg.destsize + canvasType: ['OffscreenCanvas'] + images: + - red.png + - green.png + timeout: long + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise1 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + var promise2 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + Promise.all([promise1, promise2]).then(function(response1, response2) { + var promise3 = createImageBitmap(response1); + var promise4 = createImageBitmap(response2); + Promise.all([promise3, promise4]).then(function(bitmap1, bitmap2) { + ctx.drawImage(bitmap2, 1, 1, 1, 1, 0, 0, 100, 50); + ctx.drawImage(bitmap1, 0, 0, 100, 50, -50, 0, 50, 50); + ctx.drawImage(bitmap1, 0, 0, 100, 50, 100, 0, 50, 50); + ctx.drawImage(bitmap1, 0, 0, 100, 50, 0, -25, 100, 25); + ctx.drawImage(bitmap1, 0, 0, 100, 50, 0, 50, 100, 25); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.canvas + canvasType: ['OffscreenCanvas'] + timeout: long + code: | + var offscreenCanvas2 = new OffscreenCanvas(100, 50); + var ctx2 = offscreenCanvas2.getContext('2d'); + ctx2.fillStyle = '#0f0'; + ctx2.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + ctx.drawImage(offscreenCanvas2, 0, 0); + @assert pixel 0,0 ==~ 0,255,0,255; + @assert pixel 99,0 ==~ 0,255,0,255; + @assert pixel 0,49 ==~ 0,255,0,255; + @assert pixel 99,49 ==~ 0,255,0,255; + +- name: 2d.drawImage.zerocanvas + canvasType: ['OffscreenCanvas'] + timeout: long + code: | + var offscreenCanvas2 = new OffscreenCanvas(0, 10); + @assert throws INVALID_STATE_ERR ctx.drawImage(offscreenCanvas2, 0, 0); + + offscreenCanvas2.width = 10; + offscreenCanvas2.height = 0; + @assert throws INVALID_STATE_ERR ctx.drawImage(offscreenCanvas2, 0, 0); + + offscreenCanvas2.width = 0; + offscreenCanvas2.height = 0; + @assert throws INVALID_STATE_ERR ctx.drawImage(offscreenCanvas2, 0, 0); + +- name: 2d.drawImage.floatsource + canvasType: ['OffscreenCanvas'] + timeout: long + code: | + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 10.1, 10.1, 0.1, 0.1, 0, 0, 100, 50); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.zerosource + desc: drawImage with zero-sized source rectangle draws nothing without exception + canvasType: ['OffscreenCanvas'] + timeout: long + images: + - red.png + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 10, 10, 0, 1, 0, 0, 100, 50); + ctx.drawImage(bitmap, 10, 10, 1, 0, 0, 0, 100, 50); + ctx.drawImage(bitmap, 10, 10, 0, 0, 0, 0, 100, 50); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.zerosource.image + desc: drawImage with zero-sized source rectangle from image draws nothing without exception + canvasType: ['OffscreenCanvas'] + images: + - red-zerowidth.svg + - red-zeroheight.svg + - red-zerosize.svg + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red-zerowidth.svg'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0, 100, 50); + ctx.drawImage(bitmap, 0, 0, 100, 50); + ctx.drawImage(bitmap, 0, 0, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.negativesource + desc: Negative source width/height represents the correct rectangle + canvasType: ['OffscreenCanvas'] + mozilla: {throws: !!null ''} + images: + - ggrr-256x256.png + timeout: long + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/ggrr-256x256.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 100, 78, -100, 50, 0, 0, 50, 50); + ctx.drawImage(bitmap, 100, 128, -100, -50, 50, 0, 50, 50); + @assert pixel 1,1 ==~ 0,255,0,255; + @assert pixel 1,48 ==~ 0,255,0,255; + @assert pixel 98,1 ==~ 0,255,0,255; + @assert pixel 98,48 ==~ 0,255,0,255; + @assert pixel 48,1 ==~ 0,255,0,255; + @assert pixel 48,48 ==~ 0,255,0,255; + @assert pixel 51,1 ==~ 0,255,0,255; + @assert pixel 51,48 ==~ 0,255,0,255; + @assert pixel 25,25 ==~ 0,255,0,255; + @assert pixel 75,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.negativedest + desc: Negative destination width/height represents the correct rectangle + canvasType: ['OffscreenCanvas'] + mozilla: {throws: !!null ''} + timeout: long + images: + - ggrr-256x256.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/ggrr-256x256.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 100, 78, 50, 50, 0, 50, 50, -50); + ctx.drawImage(bitmap, 100, 128, 50, -50, 100, 50, -50, -50); + @assert pixel 1,1 ==~ 0,255,0,255; + @assert pixel 1,48 ==~ 0,255,0,255; + @assert pixel 98,1 ==~ 0,255,0,255; + @assert pixel 98,48 ==~ 0,255,0,255; + @assert pixel 48,1 ==~ 0,255,0,255; + @assert pixel 48,48 ==~ 0,255,0,255; + @assert pixel 51,1 ==~ 0,255,0,255; + @assert pixel 51,48 ==~ 0,255,0,255; + @assert pixel 25,25 ==~ 0,255,0,255; + @assert pixel 75,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.negativedir + desc: Negative dimensions do not affect the direction of the image + canvasType: ['OffscreenCanvas'] + mozilla: {throws: !!null ''} + timeout: long + images: + - ggrr-256x256.png + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/ggrr-256x256.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 178, 50, -100, 0, 0, 50, 100); + ctx.drawImage(bitmap, 0, 78, 50, 100, 50, 100, 50, -100); + @assert pixel 1,1 ==~ 0,255,0,255; + @assert pixel 1,48 ==~ 0,255,0,255; + @assert pixel 98,1 ==~ 0,255,0,255; + @assert pixel 98,48 ==~ 0,255,0,255; + @assert pixel 48,1 ==~ 0,255,0,255; + @assert pixel 48,48 ==~ 0,255,0,255; + @assert pixel 51,1 ==~ 0,255,0,255; + @assert pixel 51,48 ==~ 0,255,0,255; + @assert pixel 25,25 ==~ 0,255,0,255; + @assert pixel 75,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.outsidesource + DISABLED: fix this to match the current spec (transparent black outside source) + canvasType: ['OffscreenCanvas'] + code: | + var promise1 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + var promise2 = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + Promise.all([promise1, promise2]).then(function(response1, response2) { + var promise3 = createImageBitmap(response1); + var promise4 = createImageBitmap(response2); + Promise.all([promise3, promise4]).then(function(bitmap1, bitmap2) { + ctx.drawImage(bitmap2, 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50); + ctx.drawImage(bitmap2, 5.5, 5.5, -5.5, -5.5, 0, 0, 100, 50); + ctx.drawImage(bitmap2, 100, 50, -5, -5, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, -0.001, 0, 100, 50, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, 0, -0.001, 100, 50, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, 0, 0, 100.001, 50, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, 0, 0, 100, 50.001, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, 50, 0, 50.001, 50, 0, 0, 100, 50); @moz-todo + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, 0, 0, -5, 5, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, 0, 0, 5, -5, 0, 0, 100, 50); + @assert throws INDEX_SIZE_ERR ctx.drawImage(bitmap1, 110, 60, -20, -20, 0, 0, 100, 50); + @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.broken + canvasType: ['OffscreenCanvas'] + timeout: long + code: | + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/broken.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.svg + desc: drawImage() of an SVG image + canvasType: ['OffscreenCanvas'] + timeout: long + code: | + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/green.svg'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.animated.poster + desc: drawImage() of an APNG draws the poster frame + canvasType: ['OffscreenCanvas'] + images: + - anim-poster-gr.png + timeout: long + code: | + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/anim-poster-gr.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.path + canvasType: ['OffscreenCanvas'] + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.rect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + ctx.fill(); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.transform + canvasType: ['OffscreenCanvas'] + images: + - red.png + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.translate(100, 0); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.alpha + canvasType: ['OffscreenCanvas'] + images: + - red.png + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0; + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.clip + canvasType: ['OffscreenCanvas'] + images: + - red.png + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.rect(-10, -10, 1, 1); + ctx.clip(); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.composite + canvasType: ['OffscreenCanvas'] + images: + - red.png + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalCompositeOperation = 'destination-over'; + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/red.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, 0, 0); + @assert pixel 50,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.nowrap + desc: Stretched images do not get pixels wrapping around the edges + canvasType: ['OffscreenCanvas'] + images: + - redtransparent.png + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/redtransparent.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + ctx.drawImage(bitmap, -1950, 0, 2000, 50); + @assert pixel 45,25 ==~ 0,255,0,255; + @assert pixel 50,25 ==~ 0,255,0,255; + @assert pixel 55,25 ==~ 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + +- name: 2d.drawImage.nonfinite + desc: drawImage() with Infinity/NaN is ignored + canvasType: ['OffscreenCanvas'] + images: + - red.png + timeout: long + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + var promise = new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", '/images/redtransparent.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }); + promise.then(function(response) { + createImageBitmap(response).then(bitmap => { + @nonfinite ctx.drawImage(<bitmap>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>); + @nonfinite ctx.drawImage(<bitmap>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); + @nonfinite ctx.drawImage(<bitmap>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); + @assert pixel 50,25 == 0,255,0,255; + }, t_fail); + }).then(t_pass, t_fail); + diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-rectangles-to-the-canvas.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-rectangles-to-the-canvas.yaml new file mode 100644 index 0000000000..408e932abe --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-rectangles-to-the-canvas.yaml @@ -0,0 +1,469 @@ +- name: 2d.clearRect.basic + desc: clearRect clears to transparent black + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.clearRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.clearRect.path + desc: clearRect does not affect the current path + code: | + ctx.fillStyle = '#0f0'; + ctx.beginPath(); + ctx.rect(0, 0, 100, 50); + ctx.clearRect(0, 0, 16, 16); + ctx.fill(); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.clearRect.zero + desc: clearRect of zero pixels has no effect + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.clearRect(0, 0, 100, 0); + ctx.clearRect(0, 0, 0, 50); + ctx.clearRect(0, 0, 0, 0); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.clearRect.negative + desc: clearRect of negative sizes works + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.clearRect(0, 0, 50, 25); + ctx.clearRect(100, 0, -50, 25); + ctx.clearRect(0, 50, 50, -25); + ctx.clearRect(100, 50, -50, -25); + @assert pixel 25,12 == 0,0,0,0; + @assert pixel 75,12 == 0,0,0,0; + @assert pixel 25,37 == 0,0,0,0; + @assert pixel 75,37 == 0,0,0,0; + expected: clear + +- name: 2d.clearRect.transform + desc: clearRect is affected by transforms + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.scale(10, 10); + ctx.translate(0, 5); + ctx.clearRect(0, -5, 10, 5); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.clearRect.globalalpha + desc: clearRect is not affected by globalAlpha + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalAlpha = 0.1; + ctx.clearRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.clearRect.globalcomposite + desc: clearRect is not affected by globalCompositeOperation + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.globalCompositeOperation = 'destination-atop'; + ctx.clearRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.clearRect.clip + desc: clearRect is affected by clipping regions + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.beginPath(); + ctx.rect(0, 0, 16, 16); + ctx.clip(); + ctx.clearRect(0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 16, 16); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.clearRect.shadow + desc: clearRect does not draw shadows + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.shadowColor = '#f00'; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 50; + ctx.clearRect(0, -50, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.clearRect.nonfinite + desc: clearRect() with Infinity/NaN is ignored + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + @nonfinite ctx.clearRect(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); + @assert pixel 50,25 == 0,255,0,255; + expected: green + + +- name: 2d.fillRect.basic + desc: fillRect works + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.fillRect.path + desc: fillRect does not affect the current path + code: | + ctx.beginPath(); + ctx.rect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 16, 16); + ctx.fillStyle = '#0f0'; + ctx.fill(); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.fillRect.zero + desc: fillRect of zero pixels has no effect + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 0); + ctx.fillRect(0, 0, 0, 50); + ctx.fillRect(0, 0, 0, 0); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.fillRect.negative + desc: fillRect of negative sizes works + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 50, 25); + ctx.fillRect(100, 0, -50, 25); + ctx.fillRect(0, 50, 50, -25); + ctx.fillRect(100, 50, -50, -25); + @assert pixel 25,12 == 0,255,0,255; + @assert pixel 75,12 == 0,255,0,255; + @assert pixel 25,37 == 0,255,0,255; + @assert pixel 75,37 == 0,255,0,255; + expected: green + +- name: 2d.fillRect.transform + desc: fillRect is affected by transforms + code: | + ctx.scale(10, 10); + ctx.translate(0, 5); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, -5, 10, 5); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +# don't bother testing globalalpha, globalcomposite because they're already heavily used by other test cases + +- name: 2d.fillRect.clip + desc: fillRect is affected by clipping regions + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.beginPath(); + ctx.rect(0, 0, 16, 16); + ctx.clip(); + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 16, 16); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.fillRect.shadow + desc: fillRect draws shadows + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.shadowColor = '#0f0'; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 50; + ctx.fillRect(0, -50, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.fillRect.nonfinite + desc: fillRect() with Infinity/NaN is ignored + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + @nonfinite ctx.fillRect(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); + @assert pixel 50,25 == 0,255,0,255; + expected: green + + +- name: 2d.strokeRect.basic + desc: strokeRect works + code: | + ctx.strokeStyle = '#0f0'; + ctx.lineWidth = 50; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.path + desc: strokeRect does not affect the current path + code: | + ctx.beginPath(); + ctx.rect(0, 0, 100, 50); + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 5; + ctx.strokeRect(0, 0, 16, 16); + ctx.fillStyle = '#0f0'; + ctx.fill(); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.zero.1 + desc: strokeRect of 0x0 pixels draws nothing + code: | + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 250; + ctx.strokeRect(50, 25, 0, 0); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.strokeRect.zero.2 + desc: strokeRect of 0x0 pixels draws nothing, including caps and joins + code: | + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 250; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + ctx.strokeRect(50, 25, 0, 0); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.strokeRect.zero.3 + desc: strokeRect of Nx0 pixels draws a straight line + code: | + ctx.strokeStyle = '#0f0'; + ctx.lineWidth = 50; + ctx.strokeRect(0, 25, 100, 0); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.zero.4 + desc: strokeRect of Nx0 pixels draws a closed line with no caps + code: | + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 250; + ctx.lineCap = 'round'; + ctx.strokeRect(100, 25, 100, 0); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.strokeRect.zero.5 + desc: strokeRect of Nx0 pixels draws a closed line with joins + code: | + ctx.strokeStyle = '#0f0'; + ctx.lineWidth = 250; + ctx.lineJoin = 'round'; + ctx.strokeRect(100, 25, 100, 0); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.negative + desc: strokeRect of negative sizes works + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.strokeStyle = '#0f0'; + ctx.lineWidth = 25; + ctx.strokeRect(12, 12, 26, 1); + ctx.strokeRect(88, 12, -26, 1); + ctx.strokeRect(12, 38, 26, -1); + ctx.strokeRect(88, 38, -26, -1); + @assert pixel 25,12 == 0,255,0,255; + @assert pixel 75,12 == 0,255,0,255; + @assert pixel 25,37 == 0,255,0,255; + @assert pixel 75,37 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.transform + desc: fillRect is affected by transforms + code: | + ctx.scale(10, 10); + ctx.translate(0, 5); + ctx.strokeStyle = '#0f0'; + ctx.lineWidth = 5; + ctx.strokeRect(2.5, -2.6, 5, 0.2); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.globalalpha + desc: strokeRect is affected by globalAlpha + code: | + ctx.globalAlpha = 0; + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 50; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.strokeRect.globalcomposite + desc: strokeRect is not affected by globalCompositeOperation + code: | + ctx.globalCompositeOperation = 'source-in'; + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 50; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,0,0,0; + expected: clear + +- name: 2d.strokeRect.clip + desc: strokeRect is affected by clipping regions + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.beginPath(); + ctx.rect(0, 0, 16, 16); + ctx.clip(); + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 50; + ctx.strokeRect(0, 0, 100, 50); + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 16, 16); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.shadow + desc: strokeRect draws shadows + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + ctx.shadowColor = '#0f0'; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 50; + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 50; + ctx.strokeRect(0, -75, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeRect.nonfinite + desc: strokeRect() with Infinity/NaN is ignored + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.strokeStyle = '#f00'; + ctx.lineWidth = 150; + @nonfinite ctx.strokeRect(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.fillStyle.colorObject + desc: ctx.fillStyle works with color objects + canvasType: + ['HTMLCanvas'] + code: | + ctx.fillStyle = {r: 1, g: 0, b: 0}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 255,0,0,255; + ctx.fillStyle = {r: 0, g: 0, b: 1}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,0,255,255; + ctx.fillStyle = {r: 0.2, g: 0.4, b: 0.6}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 51,102,153,255; + ctx.fillStyle = {r: 0, g: 1, b: 0}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + ctx.fillStyle = {r: -1, g: 0, b: 0}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,0,0,255; + ctx.fillStyle = {r: 0, g: 2, b: 0}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.fillStyle.colorObject.transparency + desc: ctx.fillStyle with color objects has transparency + canvasType: + ['HTMLCanvas'] + code: | + ctx.fillStyle = {r: 0, g: 1, b: 0, a: 0}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,0,0,0; + ctx.clearRect(0, 0, 100, 50); + ctx.fillStyle = {r: 0, g: 1, b: 0, a: -1}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,0,0,0; + ctx.clearRect(0, 0, 100, 50); + ctx.fillStyle = {r: 0, g: 1, b: 0, a: 0.5}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,255,0,128; + ctx.clearRect(0, 0, 100, 50); + ctx.fillStyle = {r: 0, g: 1, b: 0, a: 1}; + ctx.fillRect(0, 0, 100, 50); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeStyle.colorObject + desc: ctx.strokeStyle works with color objects + canvasType: + ['HTMLCanvas'] + code: | + ctx.lineWidth = 50; + ctx.strokeStyle = {r: 1, g: 0, b: 0}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 255,0,0,255; + ctx.strokeStyle = {r: 0, g: 0, b: 1}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,0,255,255; + ctx.strokeStyle = {r: 0.2, g: 0.4, b: 0.6}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 51,102,153,255; + ctx.strokeStyle = {r: 0, g: 1, b: 0}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,255,0,255; + ctx.strokeStyle = {r: -1, g: 0, b: 0}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,0,0,255; + ctx.strokeStyle = {r: 0, g: 2, b: 0}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,255,0,255; + expected: green + +- name: 2d.strokeStyle.colorObject.transparency + desc: ctx.strokeStyle with color objects has transparency + canvasType: + ['HTMLCanvas'] + code: | + ctx.lineWidth = 50; + ctx.strokeStyle = {r: 0, g: 1, b: 0, a: 0}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,0,0,0; + ctx.strokeStyle = {r: 0, g: 1, b: 0, a: -1}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,0,0,0; + ctx.clearRect(0, 0, 100, 50); + ctx.strokeStyle = {r: 0, g: 1, b: 0, a: 0.5}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,255,0,128; + ctx.clearRect(0, 0, 100, 50); + ctx.strokeStyle = {r: 0, g: 1, b: 0, a: 1}; + ctx.strokeRect(25, 24, 50, 2); + @assert pixel 50,25 == 0,255,0,255; + expected: green diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml new file mode 100644 index 0000000000..cc5dfe7fef --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml @@ -0,0 +1,450 @@ +- name: 2d.filter.value + desc: test if ctx.filter works correctly + code: | + @assert ctx.filter == 'none'; + ctx.filter = 'blur(5px)'; + @assert ctx.filter == 'blur(5px)'; + ctx.save(); + ctx.filter = 'none'; + @assert ctx.filter == 'none'; + ctx.restore(); + @assert ctx.filter == 'blur(5px)'; + + ctx.filter = 'blur(10)'; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = 'blur 10px'; + @assert ctx.filter == 'blur(5px)'; + + ctx.filter = 'inherit'; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = 'initial'; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = 'unset'; + @assert ctx.filter == 'blur(5px)'; + + ctx.filter = ''; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = null; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = undefined; + @assert ctx.filter == 'blur(5px)'; + + ctx.filter = 'blur( 5px)'; + assert_equals(ctx.filter, 'blur( 5px)'); + +- name: 2d.filter.canvasFilterObject.tentative + desc: Test CanvasFilter() object + canvasType: + ['HTMLCanvas'] + code: | + @assert ctx.filter == 'none'; + ctx.filter = 'blur(5px)'; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5}); + @assert ctx.filter.toString() == '[object CanvasFilter]'; + ctx.filter = new CanvasFilter([ + {filter: "gaussianBlur", stdDeviation: 5}, + {filter: "gaussianBlur", stdDeviation: 10} + ]); + @assert ctx.filter.toString() == '[object CanvasFilter]'; + var canvas2 = document.createElement('canvas'); + var ctx2 = canvas2.getContext('2d'); + ctx2.filter = ctx.filter; + @assert ctx.filter.toString() == '[object CanvasFilter]'; + ctx.filter = 'blur(5px)'; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = 'none'; + @assert ctx.filter == 'none'; + ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5}); + ctx.filter = "this string is not a filter and should do nothing"; + @assert ctx.filter.toString() == '[object CanvasFilter]'; + +- name: 2d.filter.canvasFilterObject.tentative + desc: Test CanvasFilter() object + canvasType: ['OffscreenCanvas'] + code: | + @assert ctx.filter == 'none'; + ctx.filter = 'blur(5px)'; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5}); + @assert ctx.filter.toString() == '[object CanvasFilter]'; + ctx.filter = new CanvasFilter([ + {filter: "gaussianBlur", stdDeviation: 5}, + {filter: "gaussianBlur", stdDeviation: 10} + ]); + @assert ctx.filter.toString() == '[object CanvasFilter]'; + var canvas2 = new OffscreenCanvas(100, 50); + var ctx2 = canvas2.getContext('2d'); + ctx2.filter = ctx.filter; + @assert ctx.filter.toString() == '[object CanvasFilter]'; + ctx.filter = 'blur(5px)'; + @assert ctx.filter == 'blur(5px)'; + ctx.filter = 'none'; + @assert ctx.filter == 'none'; + ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5}); + ctx.filter = "this string is not a filter and should do nothing"; + @assert ctx.filter.toString() == '[object CanvasFilter]'; + +- name: 2d.filter.canvasFilterObject.blur.exceptions.tentative + desc: Test exceptions on CanvasFilter() blur.object + code: | + @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur"}); + @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: undefined}); + @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "foo"}); + @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [1,2]}); + @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: NaN}); + @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: {}}); + +- name: 2d.filter.canvasFilterObject.colorMatrix.tentative + desc: Test the functionality of ColorMatrix filters in CanvasFilter objects + code: | + @assert throws TypeError new CanvasFilter({filter: "colorMatrix", values: undefined}); + @assert throws TypeError new CanvasFilter({filter: "colorMatrix", values: "foo"}); + @assert throws TypeError new CanvasFilter({filter: "colorMatrix", values: null}); + @assert throws TypeError new CanvasFilter({filter: "colorMatrix", values: [1, 2, 3]}); + @assert throws TypeError new CanvasFilter({filter: "colorMatrix", values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, "a"]}); + @assert throws TypeError new CanvasFilter({filter: "colorMatrix", values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, Infinity]}); + ctx.fillStyle = "#f00"; + ctx.filter = new CanvasFilter({filter: "colorMatrix", type: "hueRotate", values: 0}); + ctx.fillRect(0, 0, 100, 50); + @assert pixel 10,10 ==~ 255,0,0,255; + ctx.filter = new CanvasFilter({filter: "colorMatrix", type: "hueRotate", values: 90}); + ctx.fillRect(0, 0, 100, 50); + @assert pixel 10,10 ==~ 0,91,0,255; + ctx.filter = new CanvasFilter({filter: "colorMatrix", type: "hueRotate", values: 180}); + ctx.fillRect(0, 0, 100, 50); + @assert pixel 10,10 ==~ 0,109,109,255; + ctx.filter = new CanvasFilter({filter: "colorMatrix", type: "hueRotate", values: 270}); + ctx.fillRect(0, 0, 100, 50); + @assert pixel 10,10 ==~ 109,18,255,255; + ctx.filter = new CanvasFilter({filter: "colorMatrix", type: "saturate", values: 0.5}); + ctx.fillRect(0, 0, 100, 50); + @assert pixel 10,10 ==~ 155,27,27,255; + ctx.clearRect(0, 0, 100, 50); + ctx.filter = new CanvasFilter({filter: "colorMatrix", type: "luminanceToAlpha"}); + ctx.fillRect(0, 0, 100, 50); + @assert pixel 10,10 ==~ 0,0,0,54; + ctx.filter = new CanvasFilter({filter: "colorMatrix", values: [ + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0 + ]}); + ctx.fillRect(0, 0, 50, 25); + ctx.fillStyle = "#0f0"; + ctx.fillRect(50, 0, 50, 25); + ctx.fillStyle = "#00f"; + ctx.fillRect(0, 25, 50, 25); + ctx.fillStyle = "#fff"; + ctx.fillRect(50, 25, 50, 25); + @assert pixel 10,10 ==~ 0,255,0,255; + @assert pixel 60,10 ==~ 0,255,0,255; + @assert pixel 10,30 ==~ 0,255,0,255; + @assert pixel 60,30 ==~ 0,255,0,255; + +- name: 2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative + desc: Test exceptions on CanvasFilter() convolveMatrix + code: | + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix"}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", divisor: 2}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", kernelMatrix: null}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", kernelMatrix: 1}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", kernelMatrix: [[1, 0], [0]]}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", kernelMatrix: [[1, "a"], [0]]}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", kernelMatrix: [[1, 0], 0]}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", kernelMatrix: [[1, 0], [0, Infinity]]}); + @assert throws TypeError new CanvasFilter({filter: "convolveMatrix", kernelMatrix: []}); + // This should not throw an error + ctx.filter = new CanvasFilter({filter: "convolveMatrix", kernelMatrix: [[]]}); + +- name: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative + desc: Test pixels on CanvasFilter() componentTransfer with linear type + code: | + // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement + function getColor(inputColor, slopes, intercepts) { + return [ + Math.max(0, Math.min(1, inputColor[0]/255 * slopes[0] + intercepts[0])) * 255, + Math.max(0, Math.min(1, inputColor[1]/255 * slopes[1] + intercepts[1])) * 255, + Math.max(0, Math.min(1, inputColor[2]/255 * slopes[2] + intercepts[2])) * 255, + ]; + } + + const slopes = [0.5, 1.2, -0.2]; + const intercepts = [0.25, 0, 0.5]; + ctx.filter = new CanvasFilter({filter: "componentTransfer", + funcR: {type: "linear", slope: slopes[0], intercept: intercepts[0]}, + funcG: {type: "linear", slope: slopes[1], intercept: intercepts[1]}, + funcB: {type: "linear", slope: slopes[2], intercept: intercepts[2]}, + }); + + const inputColors = [ + [255, 255, 255], + [0, 0, 0], + [127, 0, 34], + [252, 186, 3], + [50, 68, 87], + ]; + + for (const color of inputColors) { + let outputColor = getColor(color, slopes, intercepts); + ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2); + } + +- name: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative + desc: Test pixels on CanvasFilter() componentTransfer with identity type + code: | + ctx.filter = new CanvasFilter({filter: "componentTransfer", + funcR: {type: "identity"}, + funcG: {type: "identity"}, + funcB: {type: "identity"}, + }); + + const inputColors = [ + [255, 255, 255], + [0, 0, 0], + [127, 0, 34], + [252, 186, 3], + [50, 68, 87], + ]; + + for (const color of inputColors) { + ctx.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1)`, + ctx.fillRect(0, 0, 10, 10); + _assertPixel(canvas, 5, 5, color[0],color[1],color[2],255); + } + +- name: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative + desc: Test pixels on CanvasFilter() componentTransfer with gamma type + code: | + // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement + function getColor(inputColor, amplitude, exponent, offset) { + return [ + Math.max(0, Math.min(1, Math.pow(inputColor[0]/255, exponent[0]) * amplitude[0] + offset[0])) * 255, + Math.max(0, Math.min(1, Math.pow(inputColor[1]/255, exponent[1]) * amplitude[1] + offset[1])) * 255, + Math.max(0, Math.min(1, Math.pow(inputColor[2]/255, exponent[2]) * amplitude[2] + offset[2])) * 255, + ]; + } + + const amplitudes = [2, 1.1, 0.5]; + const exponents = [5, 3, 1]; + const offsets = [0.25, 0, 0.5]; + ctx.filter = new CanvasFilter({filter: "componentTransfer", + funcR: {type: "gamma", amplitude: amplitudes[0], exponent: exponents[0], offset: offsets[0]}, + funcG: {type: "gamma", amplitude: amplitudes[1], exponent: exponents[1], offset: offsets[1]}, + funcB: {type: "gamma", amplitude: amplitudes[2], exponent: exponents[2], offset: offsets[2]}, + }); + + const inputColors = [ + [255, 255, 255], + [0, 0, 0], + [127, 0, 34], + [252, 186, 3], + [50, 68, 87], + ]; + + for (const color of inputColors) { + let outputColor = getColor(color, amplitudes, exponents, offsets); + ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2); + } + +- name: 2d.filter.canvasFilterObject.componentTransfer.table.tentative + desc: Test pixels on CanvasFilter() componentTransfer with table type + code: | + // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement + function getTransformedValue(C, V) { + // Get the right interval + const n = V.length - 1; + const k = C == 1 ? n - 1 : Math.floor(C * n); + return V[k] + (C - k/n) * n * (V[k + 1] - V[k]); + } + + function getColor(inputColor, tableValues) { + const result = [0, 0, 0]; + for (const i in inputColor) { + const C = inputColor[i]/255; + const Cprime = getTransformedValue(C, tableValues[i]); + result[i] = Math.max(0, Math.min(1, Cprime)) * 255; + } + return result; + } + + tableValuesR = [0, 0, 1, 1]; + tableValuesG = [2, 0, 0.5, 3]; + tableValuesB = [1, -1, 5, 0]; + ctx.filter = new CanvasFilter({filter: "componentTransfer", + funcR: {type: "table", tableValues: tableValuesR}, + funcG: {type: "table", tableValues: tableValuesG}, + funcB: {type: "table", tableValues: tableValuesB}, + }); + + const inputColors = [ + [255, 255, 255], + [0, 0, 0], + [127, 0, 34], + [252, 186, 3], + [50, 68, 87], + ]; + + for (const color of inputColors) { + let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]); + ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2); + } + +- name: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative + desc: Test pixels on CanvasFilter() componentTransfer with discrete type + code: | + // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement + function getTransformedValue(C, V) { + // Get the right interval + const n = V.length; + const k = C == 1 ? n - 1 : Math.floor(C * n); + return V[k]; + } + + function getColor(inputColor, tableValues) { + const result = [0, 0, 0]; + for (const i in inputColor) { + const C = inputColor[i]/255; + const Cprime = getTransformedValue(C, tableValues[i]); + result[i] = Math.max(0, Math.min(1, Cprime)) * 255; + } + return result; + } + + tableValuesR = [0, 0, 1, 1]; + tableValuesG = [2, 0, 0.5, 3]; + tableValuesB = [1, -1, 5, 0]; + ctx.filter = new CanvasFilter({filter: "componentTransfer", + funcR: {type: "discrete", tableValues: tableValuesR}, + funcG: {type: "discrete", tableValues: tableValuesG}, + funcB: {type: "discrete", tableValues: tableValuesB}, + }); + + const inputColors = [ + [255, 255, 255], + [0, 0, 0], + [127, 0, 34], + [252, 186, 3], + [50, 68, 87], + ]; + + for (const color of inputColors) { + let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]); + ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + ctx.fillRect(0, 0, 10, 10); + _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2); + } + +- name: 2d.filter.canvasFilterObject.turbulence.inputTypes.tentative + desc: Test exceptions on CanvasFilter() turbulence object + code: | + const errorTestCases = [ + {baseFrequency: {}}, + {baseFrequency: -1}, + {baseFrequency: [0, -1]}, + {baseFrequency: NaN}, + {baseFrequency: Infinity}, + {baseFrequency: undefined}, + {baseFrequency: -Infinity}, + {baseFrequency: "test"}, + + {numOctaves: {}}, + {numOctaves: -1}, + {numOctaves: NaN}, + {numOctaves: Infinity}, + {numOctaves: undefined}, + {numOctaves: -Infinity}, + {numOctaves: [1, 1]}, + {numOctaves: "test"}, + + {seed: {}}, + {seed: NaN}, + {seed: Infinity}, + {seed: undefined}, + {seed: -Infinity}, + {seed: [1, 1]}, + {seed: "test"}, + + {stitchTiles: {}}, + {stitchTiles: NaN}, + {stitchTiles: Infinity}, + {stitchTiles: undefined}, + {stitchTiles: -Infinity}, + {stitchTiles: [1, 1]}, + {stitchTiles: "test"}, + {stitchTiles: null}, + {stitchTiles: []}, + {stitchTiles: [10]}, + {stitchTiles: 30}, + {stitchTiles: false}, + {stitchTiles: true}, + {stitchTiles: "10"}, + {stitchTiles: -1}, + + {type: {}}, + {type: NaN}, + {type: Infinity}, + {type: undefined}, + {type: -Infinity}, + {type: [1, 1]}, + {type: "test"}, + {type: null}, + {type: []}, + {type: [10]}, + {type: 30}, + {type: false}, + {type: true}, + {type: "10"}, + {type: -1}, + ] + + // null and [] = 0 when parsed as number + const workingTestCases = [ + {baseFrequency: null}, + {baseFrequency: []}, + {baseFrequency: [10]}, + {baseFrequency: [10, 3]}, + {baseFrequency: 30}, + {baseFrequency: false}, + {baseFrequency: true}, + {baseFrequency: "10"}, + + {numOctaves: null}, + {numOctaves: []}, + {numOctaves: [10]}, + {numOctaves: 30}, + {numOctaves: false}, + {numOctaves: true}, + {numOctaves: "10"}, + + {seed: null}, + {seed: []}, + {seed: [10]}, + {seed: 30}, + {seed: false}, + {seed: true}, + {seed: "10"}, + {seed: -1}, + + {stitchTiles: "stitch"}, + {stitchTiles: "noStitch"}, + + {type: "fractalNoise"}, + {type: "turbulence"}, + ] + + for (testCase of errorTestCases) { + const filterOptions = {...{filter: "turbulence"}, ...testCase}; + @assert throws TypeError CanvasFilter(filterOptions); + } + + for (testCase of workingTestCases) { + const filterOptions = {...{filter: "turbulence"}, ...testCase}; + @assert new CanvasFilter(filterOptions) != null; + } diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/reset.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/reset.yaml new file mode 100644 index 0000000000..4107166248 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/reset.yaml @@ -0,0 +1,15 @@ +- name: 2d.reset.basic + desc: reset clears to transparent black + canvasType: + ['HTMLCanvas'] + code: | + ctx.fillStyle = '#f00'; + ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.reset(); + @assert pixel 0,0 == 0,0,0,0; + @assert pixel 50,25 == 0,0,0,0; + @assert pixel 25,50 == 0,0,0,0; + @assert pixel 100,50 == 0,0,0,0; + @assert pixel 0,50 == 0,0,0,0; + @assert pixel 100,0 == 0,0,0,0; + t.done();
\ No newline at end of file diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/scroll.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/scroll.yaml new file mode 100644 index 0000000000..dd088aa396 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/scroll.yaml @@ -0,0 +1,76 @@ +- name: 2d.scrollPathIntoView.basic + desc: scrollPathIntoView() works + canvasType: + ['HTMLCanvas'] + code: | + var div = document.createElement('div'); + div.style.cssText = 'width: 200vw; height: 200vh'; + document.body.appendChild(div); + canvas.style.cssText = 'position: absolute; top: 100px; left: 200px; border: none;'; + window.scrollTo(0, 0); + + ctx.beginPath(); + ctx.rect(4, 8, 16, 32); + ctx.scrollPathIntoView(); + var rect = canvas.getBoundingClientRect(); + @assert Math.round(rect.top) === -8; + @assert Math.round(rect.left) === 200; + +- name: 2d.scrollPathIntoView.verticalLR + desc: scrollPathIntoView() works in vertical-lr writing mode + canvasType: + ['HTMLCanvas'] + code: | + document.documentElement.style.cssText = 'writing-mode: vertical-lr'; + var div = document.createElement('div'); + div.style.cssText = 'width: 200vw; height: 200vh'; + document.body.appendChild(div); + canvas.style.cssText = 'position: absolute; top: 100px; left: 200px; border: none;'; + window.scrollTo(0, 0); + + ctx.beginPath(); + ctx.rect(4, 8, 16, 32); + ctx.scrollPathIntoView(); + var rect = canvas.getBoundingClientRect(); + @assert Math.round(rect.top) === 100; + @assert Math.round(rect.left) === -4; + +- name: 2d.scrollPathIntoView.verticalRL + desc: scrollPathIntoView() works in vertical-rl writing mode + canvasType: + ['HTMLCanvas'] + code: | + document.documentElement.style.cssText = 'writing-mode: vertical-rl'; + var div = document.createElement('div'); + div.style.cssText = 'width: 200vw; height: 200vh'; + document.body.appendChild(div); + canvas.style.cssText = 'position: absolute; top: 100px; right: 200px; border: none;'; + window.scrollTo(0, 0); + + ctx.beginPath(); + ctx.rect(4, 8, 16, 32); + ctx.scrollPathIntoView(); + var rect = canvas.getBoundingClientRect(); + var viewportWidth = document.scrollingElement.clientWidth; + var canvasWidth = canvas.width; + @assert Math.round(rect.top) === 100; + @assert Math.round(rect.right) === viewportWidth + (canvasWidth - 4 - 16); + +- name: 2d.scrollPathIntoView.path + desc: scrollPathIntoView() with path argument works + canvasType: + ['HTMLCanvas'] + code: | + var div = document.createElement('div'); + div.style.cssText = 'width: 200vw; height: 200vh'; + document.body.appendChild(div); + canvas.style.cssText = 'position: absolute; top: 100px; left: 200px; border: none;'; + window.scrollTo(0, 0); + + var path = new Path2D(); + path.rect(4, 8, 16, 32); + ctx.scrollPathIntoView(path); + var rect = canvas.getBoundingClientRect(); + @assert Math.round(rect.top) === -8; + @assert Math.round(rect.left) === 200; + diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/video.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/video.yaml new file mode 100644 index 0000000000..f9b48fb8da --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/video.yaml @@ -0,0 +1,10 @@ +- name: 2d.video.invalid + desc: Verify test doesn't crash with invalid video. + canvasType: + ['HTMLCanvas'] + code: | + var v = document.createElement('video'); + v.play(); + // Test is deliberately not waiting for the 'playing' event to fire. + ctx.createPattern(v, 'repeat-x'); + ctx.drawImage(v, 0, 0); |