diff options
Diffstat (limited to 'testing/web-platform/tests/html/canvas/element/manual/shadows')
6 files changed, 342 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_001.htm b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_001.htm new file mode 100644 index 0000000000..1763950d61 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_001.htm @@ -0,0 +1,60 @@ +<!doctype HTML> +<html> + <head> + <title>HTML5 Canvas Test: Shadows for linear gradients</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="author" title="Microsoft" href="http://www.microsoft.com" /> + <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" /> + <meta name="assert" content="Shadows must be drawn for linear gradients." /> + <script type="text/javascript"> + async_test(function(t) { + window.addEventListener("load", t.step_func_done(function runTest() { + var canvas = document.getElementById("canvas1"); + var ctx = canvas.getContext("2d"); + + // Draw a red rectangle. + ctx.fillStyle = "rgba(255, 0, 0, 1.0)"; + ctx.fillRect(150, 0, 100, 50); + + // Set shadow styles to draw a black shadow to overlap the red rectangle. + ctx.shadowOffsetX = 150; + ctx.shadowColor = "rgba(0, 0, 0, 1.0)"; + + // Draw a left to right, green-to-blue linear gradient. + var lingrad = ctx.createLinearGradient(0, 50, 100, 50); + lingrad.addColorStop(0, "rgba(0, 255, 0, 1.0)"); + lingrad.addColorStop(1, "rgba(0, 0, 255, 1.0)"); + ctx.fillStyle = lingrad; + ctx.fillRect(0, 0, 100, 50); + + // Check the red is gone + var data = ctx.getImageData(150, 0, 100, 50); + for (var i = 0; i < data.data.length; i += 4) { + var r = data.data[i]; + var g = data.data[i+1]; + var b = data.data[i+2]; + var a = data.data[i+3]; + assert_equals(r, 0, "r channel"); + assert_equals(g, 0, "g channel"); + assert_equals(b, 0, "b channel"); + assert_equals(a, 0xFF, "a channel"); + } + + for (var j = 0; j < data.data.length; j += 4) { + var r2 = data.data[j]; + var g2 = data.data[j+1]; + var b2 = data.data[j+2]; + var a2 = data.data[j+3]; + assert_false(r2 == 0xFF && g2 == 0 && b2 == 0 && a2 == 0xFF, "no red"); + } + })); + }, "linear gradient fillRect draws shadow (black rectange)"); + </script> + </head> + <body> + <p>Description: Shadows must be drawn for linear gradients.</p> + <p>Test passes if there is one gradient filled rectangle and one black rectangle, and no red seen on the page.</p> + <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas> + </body> +</html> diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002-ref.htm new file mode 100644 index 0000000000..0658be808e --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002-ref.htm @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>HTML5 Canvas Test: Shadows for images</title> + <link rel="author" title="Microsoft" href="http://www.microsoft.com" /> + <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" /> + <meta name="assert" content="Shadows must be drawn for images." /> + <script type="text/javascript"> + function runTest() { + var canvas = document.getElementById("canvas1"); + var ctx = canvas.getContext("2d"); + + // Draw a black rectangle image on the canvas. + var img = document.getElementById("imgBlackRect"); + ctx.drawImage(img, 0, 0); + ctx.drawImage(img, 150, 0); + } + </script> + + </head> + <body onload="runTest()"> + <p>Description: Shadows must be drawn for images.</p> + <p>Test passes if two black rectangles are shown and there is no red visible on the page.</p> + <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas> + <img id="imgBlackRect" style="display:none;" width="100" height="50" src="/images/black-rectangle.png"> + </body> +</html> diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002.htm b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002.htm new file mode 100644 index 0000000000..908fffea13 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002.htm @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>HTML5 Canvas Test: Shadows for images</title> + <link rel="author" title="Microsoft" href="http://www.microsoft.com" /> + <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" /> + <link rel="match" href="canvas_shadows_002-ref.htm" /> + <meta name="assert" content="Shadows must be drawn for images." /> + <script type="text/javascript"> + function runTest() { + var canvas = document.getElementById("canvas1"); + var ctx = canvas.getContext("2d"); + + // Draw a red rectangle. + ctx.fillStyle = "rgba(255, 0, 0, 1.0)"; + ctx.fillRect(150, 0, 100, 50); + + // Set shadow styles to draw a black shadow to overlap the red rectangle. + ctx.shadowOffsetX = 150; + ctx.shadowColor = "rgba(0, 0, 0, 1.0)"; + + // Draw a black rectangle image on the canvas. + var img = document.getElementById("imgBlackRect"); + ctx.drawImage(img, 0, 0); + } + </script> + </head> + <body onload="runTest()"> + <p>Description: Shadows must be drawn for images.</p> + <p>Test passes if two black rectangles are shown and there is no red visible on the page.</p> + <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas> + <img id="imgBlackRect" style="display:none" width="100" height="50" src="/images/black-rectangle.png"> + </body> +</html> diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors-expected.html b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors-expected.html new file mode 100644 index 0000000000..e568aa9a5c --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors-expected.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>System Colors work for Canvas Drop-Shadow Filters</title> +</head> +<body> +<div style="width: 100px; height: 100px; background-color: black"></div> +<div style="width: 100px; height: 100px; background-color: GrayText"></div> +</body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors.html b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors.html new file mode 100644 index 0000000000..42978fb18f --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>System Colors work for Canvas Drop-Shadow Filters</title> + <link rel="match" href="canvas_shadows_system_colors-expected.html"> +</head> +<body> +<canvas id='c' width="100" height="200"> +<script> +// See crbug.com/1226282 and crbug.com/1081945 +// A reference test is necessary because system colors do not have defined +// numeric values. Here we're comparing 'GrayText' to css 'GrayText'. +var ctx = document.getElementById('c').getContext('2d'); +ctx.filter = 'drop-shadow(0px 100px 0 GrayText)'; +ctx.fillRect(0,0,100,100); +</script> +</body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/shadowBlur_gaussian_tolerance.1.html b/testing/web-platform/tests/html/canvas/element/manual/shadows/shadowBlur_gaussian_tolerance.1.html new file mode 100644 index 0000000000..eec27bf108 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/shadowBlur_gaussian_tolerance.1.html @@ -0,0 +1,191 @@ +<!DOCTYPE HTML> +<title>Test of canvas shadowBlur Gaussian blur pixel values</title> +<meta charset=UTF-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<h1>Test of canvas shadowBlur Gaussian blur pixel values</h1> +<script> + +/** + * See https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions + */ +function erf(x) { + if (x < 0) { + return -erf(-x); + } + var p = 0.3275911, a1 = 0.254829592, a2 = -0.284496736, a3 = 1.421413741, a4 = -1.453152027, a5 = 1.061405429; + var t = 1 / (1 + p * x); + return 1 - Math.exp(-x * x) * t * (a1 + t * (a2 + t * (a3 + t * (a4 + t * a5)))); +} + +/** + * See https://en.wikipedia.org/wiki/Normal_distribution#Cumulative_distribution_function + * and https://en.wikipedia.org/wiki/Normal_distribution#Numerical_approximations_for_the_normal_CDF + */ +function standard_normal_distribution_cumulative(x) { + return 0.5 * (1 + erf(x / Math.SQRT2)); +} + +/** + * Verify a single pixel; helper for run_blur_test. + * params - same as run_blur_test + * row & col - relative to the corner of the rectangle being blurred + * actual - actual color found there on the canvas + */ +function test_pixel(params, row, col, shadowOffset, actual) { + var expected_gaussian; + if (params.expected_sigma > 0) { + // Compute positions within a standard normal distribution (i.e., + // where mean (μ) is and standard deviation (σ) is 1) in both + // dimensions. + // Add 0.5 because we want the middle of the pixel rather than the edge. + var pos_x = (col - shadowOffset + 0.5) / params.expected_sigma; + var pos_y = (row - shadowOffset + 0.5) / params.expected_sigma; + + // Find the expected color value based on a Gaussian blur function. + // Since we're blurring the corner of a "very large" rectangle, we + // can, instead of sampling all of the pixels, use the cumulative + // form of the normal (Gaussian) distribution and pass it the + // position of the color transition (the edges of the rectangle), + // since we know everything above and to the left of that position + // is one color, and everything that is either below or to the right + // of that position is another color. + // + // NOTE: This assumes color-interpolation happens in sRGB rather + // than linearRGB. The canvas spec doesn't appear to be clear on + // this point. If it were linearRGB, we'd need to apply the + // correction after doing this calculation. (No correction to the + // input is needed since the input is all 0 or 1.) + expected_gaussian = standard_normal_distribution_cumulative(-pos_x) * + standard_normal_distribution_cumulative(-pos_y); + } else { + if (col >= shadowOffset || row >= shadowOffset) { + expected_gaussian = 0; + } else { + expected_gaussian = 1; + } + } + // TODO: maybe also compute expected value by triple box blur? + + /* + * https://html.spec.whatwg.org/multipage/canvas.html#when-shadows-are-drawn + * describes how to draw shadows in canvas. It says, among other things: + * + * Perform a 2D Gaussian Blur on B, using σ as the standard deviation. + * + * without giving *any* allowance for error. + * + * However, other specifications that require Gaussian blurs allow some + * error; https://www.w3.org/TR/css-backgrounds-3/#shadow-blur allows up to + * 5%, and https://drafts.fxtf.org/filter-effects/#feGaussianBlurElement + * allows use of a triple box blur which is within 3%. + * + * Since expecting zero error is unreasonable, this test tests for the least + * restrictive of these bounds, the 5% error. + * + * Note that this allows 5% error in the color component, but there's no + * tolerance for error in the position; see comment below about sizes. + */ + + // Allow any rounding direction. + var min_b = Math.max( 0, Math.floor((expected_gaussian - 0.05) * 255)); + var max_b = Math.min(255, Math.ceil ((expected_gaussian + 0.05) * 255)); + var min_r = 255 - max_b; + var max_r = 255 - min_b; + + var pos = "at row " + row + " col " + col + " "; + + assert_true(min_r <= actual.r && actual.r <= max_r, + pos + "red component " + actual.r + " should be between " + + min_r + " and " + max_r + " (inclusive)."); + assert_true(min_b <= actual.b && actual.b <= max_b, + pos + "blue component " + actual.b + " should be between " + + min_b + " and " + max_b + " (inclusive)."); + assert_equals(actual.g, 0, pos + "green component should be 0"); + assert_equals(actual.a, 255, pos + "alpha component should be 255"); +} + +/** + * Run a test of a single shadowBlur drawing operation. Expects a + * parameters object containing: + * name - name of test + * canvas_width - width of canvas to create + * canvas_height - height of canvas to create + * shadowBlur - shadowBlur to use for the test drawing operation + * expected_sigma - the standard deviation of the gaussian function + * that shadowBlur is expected to produce + * pixel_skip - how many pixels to skip when sampling results. Should + * be relatively prime with canvas_width. + */ +function run_blur_test(params) { + test(function() { + var canvas = document.createElement("canvas"); + canvas.setAttribute("width", params.canvas_width); + canvas.setAttribute("height", params.canvas_height); + document.body.appendChild(canvas); + var cx = canvas.getContext("2d"); + + cx.fillStyle = "red"; + cx.fillRect(0, 0, params.canvas_width, params.canvas_height); + + // Fill a huge rect just to the top and left of the canvas, with its shadow + // blur centered at the middle of the canvas. + let edge = Math.floor(params.canvas_width / 2); // position of vertical + let big = Math.max(Math.ceil(params.expected_sigma * 1000), + params.canvas_width, + params.canvas_height); + cx.shadowBlur = params.shadowBlur; + cx.fillStyle = "green"; + cx.shadowColor = "blue"; + cx.shadowOffsetX = edge; + cx.shadowOffsetY = edge; + cx.fillRect(-big, -big, big, big); + + var imageData = + cx.getImageData(0, 0, params.canvas_width, params.canvas_height); + for (var i = 0, i_max = params.canvas_width * params.canvas_height; + i < i_max; + i += params.pixel_skip) { + var row = Math.floor(i / params.canvas_width); + var col = i - row * params.canvas_width; + + var actual = { r: imageData.data[i * 4], + g: imageData.data[i * 4 + 1], + b: imageData.data[i * 4 + 2], + a: imageData.data[i * 4 + 3] }; + + test_pixel(params, row, col, edge, actual); + } + }, "shadowBlur Gaussian pixel values for " + params.name); +} + +run_blur_test({ + name: "no blur", + canvas_width: 4, + canvas_height: 4, + shadowBlur: 0, + expected_sigma: 0, + pixel_skip: 1 +}); +run_blur_test({ + name: "small blur", + canvas_width: 20, + canvas_height: 20, + // Try to test something smaller than 8 due to historic change in + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=10647 , but not too + // small, to avoid the error from rounding to individual pixels worth + // of box blur. + shadowBlur: 6, + expected_sigma: 3, + pixel_skip: 3 +}); +run_blur_test({ + name: "large blur", + canvas_width: 100, + canvas_height: 100, + shadowBlur: 30, + expected_sigma: 15, + pixel_skip: 13 +}); +</script> |