JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div style="float: left;">
<canvas id="canvas1" width="50" height="50" style="border: 1px solid #000000; float: left;"></canvas>
<div id="canvas1_info" style="float: left; clear: both;"></div>
</div>
<div style="float: left; clear: both; margin-top: 100px;">
<canvas id="canvas2" width="1" height="1" style="border: 1px solid #000000; float: left;"></canvas>
<div id="canvas2_info" style="float: left; clear: both;"></div>
</div>
</body>
</html>
JavaScript
$(document).ready(function() {
var iters = 32; // Number of stamp iterations.
var rgba = [127, 0, 0, 2]; // Color to use for stamp iterations.
// Truncate the given value to 4 decimal places without rounding.
function trunc4(val) {
return Math.floor(val * 10000) / 10000;
}
// Stamp the requested color on the canvas the given number of times.
// At the end of the stamping process, the resulting color is compared
// to a precise calculated value based on an unmodified Porter-Duff
// source-over-dest blend function.
function stampOnCanvas(canvas) {
var context = canvas.getContext("2d");
context.globalCompositeOperation = "lighter";
// Set the fill style to our requested color.
context.fillStyle = "rgba(" + rgba[0] + "," + rgba[1] + "," + rgba[2] + "," + rgba[3] / 255.0 + ")";
// Maintain an expected, calculated color value based on the custom blend func.
var calc;
var calc_old = [0.0, 0.0, 0.0, 0.0];
var calc_old_noround = [0.0, 0.0, 0.0, 0.0];
// Keep track of each intermediate blend result to watch for rounding errors.
var trace = "Intermediate values:<br />";
// Stamp the color on the canvas the requested number of times.
for (var i = 0; i < iters; ++i) {
calc = srcOverDstBlend(rgba, calc_old);
var color = context.getImageData(0, 0, 1, 1).data;
trace += "(" + i + ") | Result: [" + color[0] + ", " + color[1] + ", " + color[2] + ", " + color[3] + "] -|- Expected: ";
trace += "[" + trunc4(calc_old_noround[0]) + ", " + trunc4(calc_old_noround[1]) + ", " + trunc4(calc_old_noround[2]) + ", " + trunc4(calc_old_noround[3]) + "]<br />";
context.fillRect(0, 0, canvas.width, canvas.height);
// Update trace variables.
calc_old_noround = calc;
calc_old =...