I've been working on a Typescript based touch screen client for our CQC home automation platform, and ran across something odd. There are lots of places where various graphical elements are layered over images. When it's time to update some area of the screen, I set a clip area and update.
But I always ended up with a line around everything, which was the color of the underlying color fill behind the image. I of course blamed myself. But, in the end, instead of committing suicide, I did a little test program.
It seems to indicate that drawImage() does NOT include the clip path boundary, while a color fill does. So blitting over the part of the images that underlies the area I'm updating doesn't completely fill the target area, leaving a line around the area.
After that simple program demonstrated the problem, I went back and for image updates I inflated the clip area by one, but left it alone for everything else, and now it's all working. I tested this in Chrome and Edge, just to make sure it wasn't some bug, and they both act exactly the same.
Strangely, I've never see any statement in the docs about whether clip paths are intended to be exclusive or inclusive of the boundary, but surely it shouldn't be one way for one type of primitive and another way for others, right?
function drawRect(ctx, x, y, w, h) {
ctx.moveTo(x, y);
ctx.lineTo(x + w, y);
ctx.lineTo(x + w, y + h);
ctx.lineTo(x, y + h);
ctx.lineTo(x, y);
}
function init()
{
var canvas = document.getElementById("output");
canvas.style.width = 480;
canvas.style.height = 480;
canvas.width = 480;
canvas.height = 480;
var drawCtx = canvas.getContext("2d");
drawCtx.translate(0.5, 0.5);
var img = new Image();
img.src = "test.jpg";
img.onload = function() {
// DRaw the image
drawCtx.drawImage(img, 0, 0);
// SEt a clip path
drawCtx.beginPath();
drawRect(drawCtx, 10, 10, 200, 200);
drawCtx.clip();
// Fill the whole area, which fills the clip area
drawCtx.fillStyle = "black";
drawCtx.fillRect(0, 0, 480, 480);
// Draw the image again, which should fill the area
drawCtx.drawImage(img, 0, 0);
// But it ends up with a black line around it
}
}
window.addEventListener("load", init, false);