summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/compositing/canvas-composite-modes.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/css/compositing/canvas-composite-modes.html
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/compositing/canvas-composite-modes.html')
-rw-r--r--testing/web-platform/tests/css/compositing/canvas-composite-modes.html157
1 files changed, 157 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/compositing/canvas-composite-modes.html b/testing/web-platform/tests/css/compositing/canvas-composite-modes.html
new file mode 100644
index 0000000000..c1aae52ce6
--- /dev/null
+++ b/testing/web-platform/tests/css/compositing/canvas-composite-modes.html
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Test of &lt;composite-mode&gt; values in canvas globalCompositeOperation</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/C#compositing">
+<link rel="help" href="https://drafts.fxtf.org/compositing/#canvascompositingandblending">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<canvas id="canvas" width="2" height="2"></canvas>
+
+<script>
+
+// Test a small set of sRGB color and alpha values in the 0-255 range.
+const VALUES = [ 0, 47, 193, 255 ];
+
+const COMPOSITE_OPERATORS = {
+ // Define a "color" function accepting source and destination colors
+ // and alphas, and an "alpha" function accepting source and
+ // destination alphas.
+ "clear": {
+ "color": (sa, sc, da, dc) => 0,
+ "alpha": (sa, da) => 0
+ },
+ "copy": {
+ "color": (sa, sc, da, dc) => sa * sc,
+ "alpha": (sa, da) => sa
+ },
+ "destination": {
+ // TODO(dbaron): The spec says this should work, but none of
+ // Chromium, Gecko, or WebKit appear to implement it.
+ "color": (sa, sc, da, dc) => da * dc,
+ "alpha": (sa, da) => da
+ },
+ "source-over": {
+ "color": (sa, sc, da, dc) => sa * sc + da * dc * (1 - sa),
+ "alpha": (sa, da) => sa + da * (1 - sa)
+ },
+ "destination-over": {
+ "color": (sa, sc, da, dc) => sa * sc * (1 - da) + da * dc,
+ "alpha": (sa, da) => sa * (1 - da) + da
+ },
+ "source-in": {
+ "color": (sa, sc, da, dc) => sa * sc * da,
+ "alpha": (sa, da) => sa * da
+ },
+ "destination-in": {
+ "color": (sa, sc, da, dc) => da * dc * sa,
+ "alpha": (sa, da) => da * sa
+ },
+ "source-out": {
+ "color": (sa, sc, da, dc) => sa * sc * (1 - da),
+ "alpha": (sa, da) => sa * (1 - da)
+ },
+ "destination-out": {
+ "color": (sa, sc, da, dc) => da * dc * (1 - sa),
+ "alpha": (sa, da) => da * (1 - sa)
+ },
+ "source-atop": {
+ "color": (sa, sc, da, dc) => sa * sc * da + da * dc * (1 - sa),
+ "alpha": (sa, da) => sa * da + da * (1 - sa)
+ },
+ "destination-atop": {
+ "color": (sa, sc, da, dc) => sa * sc * (1 - da) + da * dc * sa,
+ "alpha": (sa, da) => sa * (1 - da) + da * sa
+ },
+ "xor": {
+ "color": (sa, sc, da, dc) => sa * sc * (1 - da) + da * dc * (1 - sa),
+ "alpha": (sa, da) => sa * (1 - da) + da * (1 - sa)
+ },
+ "lighter": {
+ // TODO(https://github.com/w3c/fxtf-drafts/issues/446): All engines
+ // actually implement 'lighter' using the formula for 'plus-lighter'
+ // given below; we should update the spec to match!
+ "color": (sa, sc, da, dc) => sa * sc + da * dc,
+ "alpha": (sa, da) => sa + da
+ },
+ "plus-darker": {
+ // TODO(https://github.com/w3c/fxtf-drafts/issues/447): This formula
+ // is almost certainly wrong. It doesn't make sense, and the one
+ // engine that implements this value (WebKit) does something very
+ // different.
+ "color": (sa, sc, da, dc) => Math.max(0, 1 - sa * sc + 1 - da * dc),
+ "alpha": (sa, da) => Math.max(0, 1 - sa + 1 - da)
+ },
+ "plus-lighter": {
+ "color": (sa, sc, da, dc) => Math.min(1, sa * sc + da * dc),
+ "alpha": (sa, da) => Math.min(1, sa + da)
+ }
+};
+
+let canvas = document.getElementById("canvas");
+let cx = canvas.getContext("2d", { willReadFrequently: true });
+
+function roundup_255th(n) {
+ return Math.ceil(n * 255) / 255;
+}
+
+function rounddown_255th(n) {
+ return Math.floor(n * 255) / 255;
+}
+
+for (let op in COMPOSITE_OPERATORS) {
+ test(function() {
+ cx.save();
+ this.add_cleanup(() => { cx.restore(); });
+ for (let sc of VALUES) {
+ for (let sa of VALUES) {
+ for (let dc of VALUES) {
+ for (let da of VALUES) {
+ let desc = `g=${sc} a=${sa} ${op} g=${dc} a=${da}`;
+ cx.restore();
+ cx.save();
+ cx.clearRect(0, 0, 2, 2);
+ cx.fillStyle = `rgb(0, ${dc}, 0)`;
+ cx.globalAlpha = da / 255;
+ cx.fillRect(0, 0, 2, 2);
+ cx.globalCompositeOperation = op;
+ assert_equals(cx.globalCompositeOperation, op, "composite operation");
+ cx.fillStyle = `rgb(0, ${sc}, 0)`;
+ cx.globalAlpha = sa / 255;
+ cx.fillRect(0, 0, 2, 2);
+ let imageData = cx.getImageData(0, 0, 1, 1);
+ assert_equals(imageData.data.length, 4, "length of ImageData");
+ assert_equals(imageData.data[0], 0, `red: ${desc}`);
+ assert_equals(imageData.data[2], 0, `blue: ${desc}`);
+ let expected_color = COMPOSITE_OPERATORS[op].color(sa/255, sc/255, da/255, dc/255);
+ let expected_alpha = COMPOSITE_OPERATORS[op].alpha(sa/255, da/255);
+ let allowed_color_error;
+ // undo the premultiplication:
+ if (expected_alpha == 0) {
+ assert_equals(expected_color, 0, `premultiplication zero check: ${desc}`);
+ allowed_color_error = 0;
+ } else {
+ // We want to allow for the error in the color expectation
+ // to increase when the expected alpha is small, because
+ // we want to allow for roughly the same amount of error
+ // in the (smaller) *premultiplied* value.
+ let expected_min_color = rounddown_255th(expected_color) / roundup_255th(expected_alpha);
+ let expected_max_color = roundup_255th(expected_color) / rounddown_255th(expected_alpha);
+ // Set the expectation to the midpoint of the error range
+ // rather than the actual accurate expectation.
+ expected_color = (expected_max_color + expected_min_color) / 2;
+ allowed_color_error = (expected_max_color - expected_min_color) / 2;
+ }
+ expected_color *= 255;
+ expected_alpha *= 255;
+ allowed_color_error *= 255;
+ allowed_color_error += 3.5;
+ assert_approx_equals(imageData.data[1], expected_color, allowed_color_error, `green: ${desc}`);
+ assert_approx_equals(imageData.data[3], expected_alpha, 1.01, `alpha: ${desc}`);
+ }
+ }
+ }
+ }
+ }, `globalCompositeOperation ${op}`);
+}
+</script>