Skip to content

Commit

Permalink
Implement colorMatrix filters for CanvasFilter objects
Browse files Browse the repository at this point in the history
The existing SVG interface has been copied exactly, even when it doesn't
make a ton of sense, for example:
  ctx.filter = new CanvasFilter({colorMatrix: {type: "saturate", values: 0.5}});
Uses the key "values" instead of "value", even though it's only a single
number.

Bug: 1169216
Change-Id: I6242f1909645ee4a2f7a6258b6563b44f3eb76eb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2855935
Commit-Queue: Aaron Krajeski <aaronhk@chromium.org>
Reviewed-by: Juanmi Huertas <juanmihd@chromium.org>
Reviewed-by: Yi Xu <yiyix@chromium.org>
Cr-Commit-Position: refs/heads/master@{#879788}
  • Loading branch information
mysteryDate authored and chromium-wpt-export-bot committed May 6, 2021
1 parent a03d7c3 commit fc59469
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 0 deletions.
@@ -0,0 +1,69 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<title>Canvas test: 2d.filter.canvasFilterObject.colorMatrix</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/html/canvas/resources/canvas-tests.js"></script>
<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
<body class="show_output">

<h1>2d.filter.canvasFilterObject.colorMatrix</h1>
<p class="desc">Test the functionality of ColorMatrix filters in CanvasFilter objects</p>


<p class="output">Actual output:</p>
<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
<ul id="d"></ul>
<script>
var t = async_test("Test the functionality of ColorMatrix filters in CanvasFilter objects");
_addTest(function(canvas, ctx) {

assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: undefined}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: "foo"}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: null}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: [1, 2, 3]}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, "a"]}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({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({colorMatrix: {type: "hueRotate", values: 0}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 255,0,0,255, "10,10", "255,0,0,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 90}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,91,0,255, "10,10", "0,91,0,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 180}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,109,109,255, "10,10", "0,109,109,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 270}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 109,18,255,255, "10,10", "109,18,255,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "saturate", values: 0.5}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 155,27,27,255, "10,10", "155,27,27,255", 2);
ctx.clearRect(0, 0, 100, 50);
ctx.filter = new CanvasFilter({colorMatrix: {type: "luminanceToAlpha"}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,0,0,54, "10,10", "0,0,0,54", 2);
ctx.filter = new CanvasFilter({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);
_assertPixelApprox(canvas, 10,10, 0,255,0,255, "10,10", "0,255,0,255", 2);
_assertPixelApprox(canvas, 60,10, 0,255,0,255, "60,10", "0,255,0,255", 2);
_assertPixelApprox(canvas, 10,30, 0,255,0,255, "10,30", "0,255,0,255", 2);
_assertPixelApprox(canvas, 60,30, 0,255,0,255, "60,30", "0,255,0,255", 2);


});
</script>

@@ -0,0 +1,68 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<title>OffscreenCanvas test: 2d.filter.canvasFilterObject.colorMatrix</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/html/canvas/resources/canvas-tests.js"></script>

<h1>2d.filter.canvasFilterObject.colorMatrix</h1>
<p class="desc">Test the functionality of ColorMatrix filters in CanvasFilter objects</p>


<script>
var t = async_test("Test the functionality of ColorMatrix filters in CanvasFilter objects");
var t_pass = t.done.bind(t);
var t_fail = t.step_func(function(reason) {
throw reason;
});
t.step(function() {

var offscreenCanvas = new OffscreenCanvas(100, 50);
var ctx = offscreenCanvas.getContext('2d');

assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: undefined}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: "foo"}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: null}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: [1, 2, 3]}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, "a"]}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({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({colorMatrix: {type: "hueRotate", values: 0}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 255,0,0,255, "10,10", "255,0,0,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 90}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 0,91,0,255, "10,10", "0,91,0,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 180}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 0,109,109,255, "10,10", "0,109,109,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 270}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 109,18,255,255, "10,10", "109,18,255,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "saturate", values: 0.5}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 155,27,27,255, "10,10", "155,27,27,255", 2);
ctx.clearRect(0, 0, 100, 50);
ctx.filter = new CanvasFilter({colorMatrix: {type: "luminanceToAlpha"}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 0,0,0,54, "10,10", "0,0,0,54", 2);
ctx.filter = new CanvasFilter({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);
_assertPixelApprox(offscreenCanvas, 10,10, 0,255,0,255, "10,10", "0,255,0,255", 2);
_assertPixelApprox(offscreenCanvas, 60,10, 0,255,0,255, "60,10", "0,255,0,255", 2);
_assertPixelApprox(offscreenCanvas, 10,30, 0,255,0,255, "10,30", "0,255,0,255", 2);
_assertPixelApprox(offscreenCanvas, 60,30, 0,255,0,255, "60,30", "0,255,0,255", 2);
t.done();
});
</script>
@@ -0,0 +1,64 @@
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.colorMatrix
// Description:Test the functionality of ColorMatrix filters in CanvasFilter objects
// Note:

importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");

var t = async_test("Test the functionality of ColorMatrix filters in CanvasFilter objects");
var t_pass = t.done.bind(t);
var t_fail = t.step_func(function(reason) {
throw reason;
});
t.step(function() {

var offscreenCanvas = new OffscreenCanvas(100, 50);
var ctx = offscreenCanvas.getContext('2d');

assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: undefined}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: "foo"}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: null}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: [1, 2, 3]}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({colorMatrix: {values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, "a"]}}); });
assert_throws_js(TypeError, function() { new CanvasFilter({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({colorMatrix: {type: "hueRotate", values: 0}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 255,0,0,255, "10,10", "255,0,0,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 90}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 0,91,0,255, "10,10", "0,91,0,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 180}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 0,109,109,255, "10,10", "0,109,109,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 270}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 109,18,255,255, "10,10", "109,18,255,255", 2);
ctx.filter = new CanvasFilter({colorMatrix: {type: "saturate", values: 0.5}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 155,27,27,255, "10,10", "155,27,27,255", 2);
ctx.clearRect(0, 0, 100, 50);
ctx.filter = new CanvasFilter({colorMatrix: {type: "luminanceToAlpha"}});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(offscreenCanvas, 10,10, 0,0,0,54, "10,10", "0,0,0,54", 2);
ctx.filter = new CanvasFilter({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);
_assertPixelApprox(offscreenCanvas, 10,10, 0,255,0,255, "10,10", "0,255,0,255", 2);
_assertPixelApprox(offscreenCanvas, 60,10, 0,255,0,255, "60,10", "0,255,0,255", 2);
_assertPixelApprox(offscreenCanvas, 10,30, 0,255,0,255, "10,30", "0,255,0,255", 2);
_assertPixelApprox(offscreenCanvas, 60,30, 0,255,0,255, "60,30", "0,255,0,255", 2);
t.done();
});
done();
48 changes: 48 additions & 0 deletions html/canvas/tools/yaml/element/filters.yaml
Expand Up @@ -61,3 +61,51 @@
@assert throws TypeError ctx.filter = new CanvasFilter({blur: {}});
@assert throws TypeError ctx.filter = new CanvasFilter({blur: {stdDevation: null}});
@assert throws TypeError ctx.filter = new CanvasFilter({blur: {stdDeviation: "foo"}});
- name: 2d.filter.canvasFilterObject.colorMatrix
desc: Test the functionality of ColorMatrix filters in CanvasFilter objects
code: |
@assert throws TypeError new CanvasFilter({colorMatrix: {values: undefined}});
@assert throws TypeError new CanvasFilter({colorMatrix: {values: "foo"}});
@assert throws TypeError new CanvasFilter({colorMatrix: {values: null}});
@assert throws TypeError new CanvasFilter({colorMatrix: {values: [1, 2, 3]}});
@assert throws TypeError new CanvasFilter({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({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({colorMatrix: {type: "hueRotate", values: 0}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 255,0,0,255;
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 90}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 0,91,0,255;
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 180}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 0,109,109,255;
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 270}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 109,18,255,255;
ctx.filter = new CanvasFilter({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({colorMatrix: {type: "luminanceToAlpha"}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 0,0,0,54;
ctx.filter = new CanvasFilter({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;
expected: green
48 changes: 48 additions & 0 deletions html/canvas/tools/yaml/offscreen/filters.yaml
Expand Up @@ -29,3 +29,51 @@
@assert throws TypeError ctx.filter = new CanvasFilter({blur: {stdDevation: null}});
@assert throws TypeError ctx.filter = new CanvasFilter({blur: {stdDeviation: "foo"}});
t.done();
- name: 2d.filter.canvasFilterObject.colorMatrix
desc: Test the functionality of ColorMatrix filters in CanvasFilter objects
code: |
@assert throws TypeError new CanvasFilter({colorMatrix: {values: undefined}});
@assert throws TypeError new CanvasFilter({colorMatrix: {values: "foo"}});
@assert throws TypeError new CanvasFilter({colorMatrix: {values: null}});
@assert throws TypeError new CanvasFilter({colorMatrix: {values: [1, 2, 3]}});
@assert throws TypeError new CanvasFilter({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({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({colorMatrix: {type: "hueRotate", values: 0}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 255,0,0,255;
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 90}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 0,91,0,255;
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 180}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 0,109,109,255;
ctx.filter = new CanvasFilter({colorMatrix: {type: "hueRotate", values: 270}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 109,18,255,255;
ctx.filter = new CanvasFilter({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({colorMatrix: {type: "luminanceToAlpha"}});
ctx.fillRect(0, 0, 100, 50);
@assert pixel 10,10 ==~ 0,0,0,54;
ctx.filter = new CanvasFilter({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;
t.done();

0 comments on commit fc59469

Please sign in to comment.