Skip to content

Commit

Permalink
Fixes #348
Browse files Browse the repository at this point in the history
Turns out, firefox outplayed me. The canvas data returned in "strict
privacy" mode will not be equivalent to what you put in. Hence, we are
now keeping our own source of truth buffer to operate on, for both reads
and writes.
  • Loading branch information
Bios-Marcel committed Oct 26, 2024
1 parent b026dde commit f3728fe
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 31 deletions.
20 changes: 1 addition & 19 deletions internal/frontend/resources/floodfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ function floodfillData(data, x, y, fillcolor, width, height) {
return false;
}

var targetcolor = [data[i], data[i + 1], data[i + 2]];

//We check whether the target pixel is already the desired color, since
//filling wouldn't change any of the pixels in this case.
var targetcolor = [data[i], data[i + 1], data[i + 2]];
if (
targetcolor[0] === fillcolor.r &&
targetcolor[1] === fillcolor.g &&
Expand Down Expand Up @@ -64,7 +63,6 @@ function pixelCompare(i, targetcolor, data) {

function pixelCompareAndSet(i, targetcolor, fillcolor, data) {
if (pixelCompare(i, targetcolor, data)) {
//fill the color
data[i] = fillcolor.r;
data[i + 1] = fillcolor.g;
data[i + 2] = fillcolor.b;
Expand All @@ -86,19 +84,3 @@ function fillUint8ClampedArray(data, x, y, color, width, height) {

return floodfillData(data, xi, yi, color, width, height);
};

function floodfillContext(ctx, x, y, color) {
var image = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
var width = image.width;
var height = image.height;

if (width > 0 && height > 0) {
const hasFilled = fillUint8ClampedArray(image.data, x, y, color, width, height);
if (hasFilled) {
ctx.putImageData(image, 0, 0);
}
return hasFilled;
}

return false;
}
43 changes: 31 additions & 12 deletions internal/frontend/templates/lobby.html
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,16 @@
// Moving this here to extract the context after resizing
const context = drawingBoard.getContext("2d", {alpha: false});

// One might one wonder what the fuck is going here. I'll enlighten you!
// The data you put into a canvas, might not necessarily be what comes out
// of it again. Some browser (*cough* firefox *cough*) seem to put little
// off by one / two errors into the data, when reading it back out.
// Apparently this helps against some type of fingerprinting. In order to
// combat this, we do not use the canvas as a source of truth, but
// permanently hold a virtual canvas buffer that we can operate on when
// filling or drawing.
let imageData;

function scaleUpFactor() {
return baseWidth / drawingBoard.clientWidth;
}
Expand Down Expand Up @@ -1693,7 +1703,7 @@
function applyDrawData(drawElements) {
clear(context);
const scaleFactor = scaleDownFactor();
const canvasData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
imageData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);

// This implementation directly access the canvas data and does not
// put it back into the canvas context directly. This saved us not
Expand Down Expand Up @@ -1729,7 +1739,7 @@
const newY1 = y1 + iy - offset;
const newX2 = x2 + ix - offset;
const newY2 = y2 + iy - offset;
drawBresenhamLine(canvasData, newX1, newY1, newX2, newY2, color);
drawBresenhamLine(imageData, newX1, newY1, newX2, newY2, color);
}
}
}
Expand All @@ -1740,10 +1750,10 @@
const drawData = drawElement.data;
if (drawElement.type === "fill") {
fillUint8ClampedArray(
canvasData.data,
imageData.data,
drawData.x * scaleFactor, drawData.y * scaleFactor,
drawData.color,
canvasData.width, canvasData.height);
imageData.width, imageData.height);
} else if (drawElement.type === "line") {
_drawLine(
drawData.fromX * scaleFactor, drawData.fromY * scaleFactor,
Expand All @@ -1755,7 +1765,7 @@
}
});

context.putImageData(canvasData, 0, 0);
context.putImageData(imageData, 0, 0);
}

let lastX = 0;
Expand Down Expand Up @@ -1948,6 +1958,7 @@

drawingBoard.width = drawingBoard.clientWidth;
drawingBoard.height = drawingBoard.clientHeight;
imageData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
setLineWidth(localLineWidthUnscaled);

return true;
Expand All @@ -1956,6 +1967,7 @@
function clear(context) {
context.fillStyle = "#FFFFFF";
context.fillRect(0, 0, drawingBoard.width, drawingBoard.height);
imageData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
}

//Call intially to correct initial state
Expand All @@ -1975,7 +1987,8 @@
}, false);

function fillAndSendEvent(context, x, y, color) {
if (floodfillContext(context, x, y, color)) {
if (floodfillData(imageData.data, x, y, color, imageData.width, imageData.height)) {
context.putImageData(imageData, 0, 0);
const fillInstruction = {
type: "fill",
data: {
Expand Down Expand Up @@ -2031,21 +2044,27 @@

const circleMap = generateCircleMap(Math.floor(lineWidth / 2));
const offset = Math.floor(circleMap.length / 2);
const imageData = context.getImageData(left, top, right - left, bottom - top);

for (let ix = 0; ix < circleMap.length; ix++) {
for (let iy = 0; iy < circleMap[ix].length; iy++) {
if (circleMap[ix][iy] === 1 || (x1 === x2 && y1 === y2 && circleMap[ix][iy] === 2)) {
const newX1 = x1 + ix - offset - left;
const newY1 = y1 + iy - offset - top;
const newX2 = x2 + ix - offset - left;
const newY2 = y2 + iy - offset - top;
const newX1 = x1 + ix - offset;
const newY1 = y1 + iy - offset;
const newX2 = x2 + ix - offset;
const newY2 = y2 + iy - offset;
drawBresenhamLine(imageData, newX1, newY1, newX2, newY2, color);
}
}
}

context.putImageData(imageData, left, top);
const targetX = left;
const targetY = top;
const sourceX = left;
const sourceY = top;
const sourceWidth = right - left;
const sourceHeight = bottom - top;
//context.putImageData(imageData, targetX, targetY, sourceX, sourceY, sourceWidth, sourceHeight);
context.putImageData(imageData, 0, 0, 0, 0, right, bottom);
}

function drawBresenhamLine(imageData, x1, y1, x2, y2, color) {
Expand Down

0 comments on commit f3728fe

Please sign in to comment.