Skip to content

Commit

Permalink
Add WPT test validating that drawImage writes to the layer
Browse files Browse the repository at this point in the history
Added a WPT to check that using `drawImage` inside a layer writes the
image to the layer and not it's parent directly. The test uses
`drawImage` with another canvas as source, inside a layer that applies a
filter and uses the global composite operation `xor`. In its reference,
the same drawing commands are used in the main canvas inside the layer,
to verify that the filter effect is applied on the image, and that the
compositing of the `drawImage` operation is done with the layer's content
and not the parent's.

Bug: 1396372
Change-Id: I377b4eb0b77865c639b296df70110c2fa8f7f07f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5253602
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
Reviewed-by: Jean-Philippe Gravel <jpgravel@chromium.org>
Commit-Queue: Andres Ricardo Perez <andresrperez@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1260079}
  • Loading branch information
AndresRPerez12 authored and chromium-wpt-export-bot committed Feb 13, 2024
1 parent fccb038 commit fe09a18
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 0 deletions.
29 changes: 29 additions & 0 deletions html/canvas/element/layers/2d.layer.drawImage-expected.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<title>Canvas test: 2d.layer.drawImage</title>
<h1>2d.layer.drawImage</h1>
<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
<canvas id="canvas" width="200" height="200">
<p class="fallback">FAIL (fallback content)</p>
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, 100, 100);

ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
stdDeviation: 0, floodColor: 'navy'}});

ctx.fillStyle = 'maroon';
ctx.fillRect(20, 20, 50, 50);

ctx.globalCompositeOperation = 'xor';

// Should xor only with the layer content, not the parents'.
ctx.fillStyle = 'pink';
ctx.fillRect(40, 40, 50, 50);

ctx.endLayer();
</script>
33 changes: 33 additions & 0 deletions html/canvas/element/layers/2d.layer.drawImage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.drawImage-expected.html">
<title>Canvas test: 2d.layer.drawImage</title>
<h1>2d.layer.drawImage</h1>
<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
<canvas id="canvas" width="200" height="200">
<p class="fallback">FAIL (fallback content)</p>
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, 100, 100);

ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
stdDeviation: 0, floodColor: 'navy'}});

ctx.fillStyle = 'maroon';
ctx.fillRect(20, 20, 50, 50);

ctx.globalCompositeOperation = 'xor';

// The image should xor only with the layer content, not the parents'.
const canvas_image = new OffscreenCanvas(200,200);
const ctx_image = canvas_image.getContext("2d");
ctx_image.fillStyle = 'pink';
ctx_image.fillRect(40, 40, 50, 50);
ctx.drawImage(canvas_image, 0, 0);

ctx.endLayer();
</script>
29 changes: 29 additions & 0 deletions html/canvas/offscreen/layers/2d.layer.drawImage-expected.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<title>Canvas test: 2d.layer.drawImage</title>
<h1>2d.layer.drawImage</h1>
<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
<canvas id="canvas" width="200" height="200">
<p class="fallback">FAIL (fallback content)</p>
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, 100, 100);

ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
stdDeviation: 0, floodColor: 'navy'}});

ctx.fillStyle = 'maroon';
ctx.fillRect(20, 20, 50, 50);

ctx.globalCompositeOperation = 'xor';

// Should xor only with the layer content, not the parents'.
ctx.fillStyle = 'pink';
ctx.fillRect(40, 40, 50, 50);

ctx.endLayer();
</script>
36 changes: 36 additions & 0 deletions html/canvas/offscreen/layers/2d.layer.drawImage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.drawImage-expected.html">
<title>Canvas test: 2d.layer.drawImage</title>
<h1>2d.layer.drawImage</h1>
<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
<canvas id="canvas" width="200" height="200">
<p class="fallback">FAIL (fallback content)</p>
</canvas>
<script>
const canvas = new OffscreenCanvas(200, 200);
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, 100, 100);

ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
stdDeviation: 0, floodColor: 'navy'}});

ctx.fillStyle = 'maroon';
ctx.fillRect(20, 20, 50, 50);

ctx.globalCompositeOperation = 'xor';

// The image should xor only with the layer content, not the parents'.
const canvas_image = new OffscreenCanvas(200,200);
const ctx_image = canvas_image.getContext("2d");
ctx_image.fillStyle = 'pink';
ctx_image.fillRect(40, 40, 50, 50);
ctx.drawImage(canvas_image, 0, 0);

ctx.endLayer();

const outputCanvas = document.getElementById("canvas");
outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
</script>
50 changes: 50 additions & 0 deletions html/canvas/offscreen/layers/2d.layer.drawImage.w.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
<link rel="match" href="2d.layer.drawImage-expected.html">
<title>Canvas test: 2d.layer.drawImage</title>
<h1>2d.layer.drawImage</h1>
<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
<canvas id="canvas" width="200" height="200">
<p class="fallback">FAIL (fallback content)</p>
</canvas>
<script id='myWorker' type='text/worker'>
self.onmessage = function(e) {
const canvas = new OffscreenCanvas(200, 200);
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, 100, 100);

ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
stdDeviation: 0, floodColor: 'navy'}});

ctx.fillStyle = 'maroon';
ctx.fillRect(20, 20, 50, 50);

ctx.globalCompositeOperation = 'xor';

// The image should xor only with the layer content, not the parents'.
const canvas_image = new OffscreenCanvas(200,200);
const ctx_image = canvas_image.getContext("2d");
ctx_image.fillStyle = 'pink';
ctx_image.fillRect(40, 40, 50, 50);
ctx.drawImage(canvas_image, 0, 0);

ctx.endLayer();

const bitmap = canvas.transferToImageBitmap();
self.postMessage(bitmap, bitmap);
};
</script>
<script>
const blob = new Blob([document.getElementById('myWorker').textContent]);
const worker = new Worker(URL.createObjectURL(blob));
worker.addEventListener('message', msg => {
const outputCtx = document.getElementById("canvas").getContext('2d');
outputCtx.drawImage(msg.data, 0, 0);
document.documentElement.classList.remove("reftest-wait");
});
worker.postMessage(null);
</script>
</html>
43 changes: 43 additions & 0 deletions html/canvas/tools/yaml-new/layers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,49 @@
ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 80, 50);
- name: 2d.layer.drawImage
size: [200, 200]
desc: >-
Checks that drawImage writes the image to the layer and not the parent
directly.
code: |
ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, 100, 100);
ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
stdDeviation: 0, floodColor: 'navy'}});
ctx.fillStyle = 'maroon';
ctx.fillRect(20, 20, 50, 50);
ctx.globalCompositeOperation = 'xor';
// The image should xor only with the layer content, not the parents'.
const canvas_image = new OffscreenCanvas(200,200);
const ctx_image = canvas_image.getContext("2d");
ctx_image.fillStyle = 'pink';
ctx_image.fillRect(40, 40, 50, 50);
ctx.drawImage(canvas_image, 0, 0);
ctx.endLayer();
reference: |
ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, 100, 100);
ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
stdDeviation: 0, floodColor: 'navy'}});
ctx.fillStyle = 'maroon';
ctx.fillRect(20, 20, 50, 50);
ctx.globalCompositeOperation = 'xor';
// Should xor only with the layer content, not the parents'.
ctx.fillStyle = 'pink';
ctx.fillRect(40, 40, 50, 50);
ctx.endLayer();
- name: 2d.layer.valid-calls
desc: No exception raised on {{ variant_desc }}.
variants:
Expand Down

0 comments on commit fe09a18

Please sign in to comment.