Giter Club home page Giter Club logo

Comments (31)

exonjoe avatar exonjoe commented on May 24, 2024 4

@1j01
Yeah, I'm afraid the test page works fine for me: I'm seeing multiple stacked squares.

Just moving the selection will NOT reset the canvas
Just resizing the selection WILL reset the canvas

Moving the selection doesn't use drawImage, but resizing the selection uses drawImage. Also, drawing with most of the tools uses drawImage when done.

Resizing and then moving the selection (without "applying" the resize first by clicking outside the selection) will NOT reset the canvas

This is curious. I'm not sure I can explain that. And, well, finalizing the selection also uses drawImage, so that somewhat muddles things.

Hmm, I'm not sure whether the behavior changed or I just didn't record it properly, but it does behave a bit differently to how I explained it! Let me try again:

  • Making a selection immediately resets the canvas outside of the selection
  • Moving the selection leaves a ghost/shadow of the background color in place of the original selection
  • Clicking outside of the selection at this point to commit the change will keep the selection and the ghost
  • Resizing the selection will also leave a ghost
  • Clicking outside at this point will keep the selection, but deletes the ghost
  • In fact, I can do any combination of moving and resizing the selection, and the ghost will always disappear if the last thing I did was a resize; or the ghost will stay around if the last thing I did was a move

Quick video demo (where my background color was set to red 🟥):

Screen.Recording.2023-11-15.at.6.53.41.PM.mov

Thanks for the time you're putting into diagnosing this! I didn't realize how much I used the app until I stopped being able to use it 😅

from jspaint.

boowangoo avatar boowangoo commented on May 24, 2024 2

i wonder if there has been further updates since then…? (no pressure! ^^;;)

I reported this issue to Chromium, and it looks like they already have someone assigned.

from jspaint.

1j01 avatar 1j01 commented on May 24, 2024 1

i see multiple circles, so that means it's good?

Well it's good in that it's displaying correctly; it's not so good in that we've not identified the problem :)
Thanks for testing though!

from jspaint.

throwaway454 avatar throwaway454 commented on May 24, 2024 1

I have the same problem. Interestingly, the bug persists even when I use other online MS Paint alternatives.

from jspaint.

roeniss avatar roeniss commented on May 24, 2024 1

same problem:

macOS (macbook)
OS: 13.6
Chrome: 119.0.6045.123 (arm64)

I think it was OK 20 days ago

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024 1

I made a tweaked test page, hopefully demonstrating the bug.
Let me know if this reproduces the bug, y'all. (I feel like it won't, since it's a shot in the dark, and the Chrome team ought to have automated tests for things like this, but still...)

Screen.Recording.2023-11-15.at.7.58.02.PM.mov

aight tested the square thing, i already had a pile going before the recording, but i spam clicked even more just incase it wasn't enough

from jspaint.

boowangoo avatar boowangoo commented on May 24, 2024 1

I have also been encountering this issue. It indeed happens whenever drawImage() is called on the main context.
As others have reported, this issue only occurs on Apple Silicon (M1) Chromium browsers. Firefox for me is fine, as is Chrome on Windows.

I found that disabling Accelerated 2D canvas (chrome://flags/#disable-accelerated-2d-canvas), which is an experimental Chrome feature, did the trick.

After reloading the browser, the app works with no issue. Hopefully it gets fixed with the next Chrome update.

from jspaint.

jakew009 avatar jakew009 commented on May 24, 2024 1

I have also been encountering this issue. It indeed happens whenever drawImage() is called on the main context. As others have reported, this issue only occurs on Apple Silicon (M1) Chromium browsers. Firefox for me is fine, as is Chrome on Windows.

I found that disabling Accelerated 2D canvas (chrome://flags/#disable-accelerated-2d-canvas), which is an experimental Chrome feature, did the trick.

After reloading the browser, the app works with no issue. Hopefully it gets fixed with the next Chrome update.

You are a life saver, I can't believe how often I google jspaint to sketch something then remember it's broken due to this bug.

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024 1
Screen.Recording.2023-12-06.at.0.45.30.AM.mov

now on 120.0.6099.62 (Official Build) (x86_64) and it registers again~
(sprite is off because i enlargened my mouse but otherwise nothing off on my end)

from jspaint.

justin-himself avatar justin-himself commented on May 24, 2024

Same issue arises after I upgraded to the newest version of chrome.

Version 119.0.6045.105 (Official Build) (arm64)

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024

Same issue arises after I upgraded to the newest version of chrome.

Version 119.0.6045.105 (Official Build) (arm64)

possibly chrome itself breaks it, idk the technical who-now but updated it, build does the same thing
119.0.6045.123 (Official Build) (x86_64)

from jspaint.

1j01 avatar 1j01 commented on May 24, 2024

Ah, the wonders of software rot. (The rectangle tool also broke recently on Firefox, and I've been experiencing tons of graphical glitches and WebGL crashes recently in Chrome.)
I can't reproduce this issue though, on Ubuntu 22 or macOS 10.14.6
What operating system does this happen on? Does it happen all the time?

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024

Ah, the wonders of software rot. (The rectangle tool also broke recently on Firefox, and I've been experiencing tons of graphical glitches and WebGL crashes recently in Chrome.) I can't reproduce this issue though, on Ubuntu 22 or macOS 10.14.6 What operating system does this happen on? Does it happen all the time?

my main computer is a macbook air that's a Retina 13-inch 2020, Sonoma 14.0.
hopefully that might help find where the issue is coming from

from jspaint.

DavidComsay avatar DavidComsay commented on May 24, 2024

same here I dont whats happening but i would like it fixed.
I need to use this software for a project but i cant due to the bug

from jspaint.

1j01 avatar 1j01 commented on May 24, 2024

Does this test page show multiple circles when you click it multiple times, or just one?
I'm thinking this chromium bug could be the culprit.

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024

Does this test page show multiple circles when you click it multiple times, or just one? I'm thinking this chromium bug could be the culprit.

Screen.Recording.2023-11-10.at.4.10.48.AM.mov

i see multiple circles, so that means it's good?

from jspaint.

Eitol avatar Eitol commented on May 24, 2024

I have the same problem.
Mackbook Pro M2 Pro
macOS Sonoma 14.1
Google Chrome Versión 119.0.6045.123 (Build oficial) (arm64)

from jspaint.

barhom avatar barhom commented on May 24, 2024

Same problem

from jspaint.

twoTimesAgnew avatar twoTimesAgnew commented on May 24, 2024

same problem

macbook pro M1
macOS Sonoma 14.1
Chromium: 119.0.6045.105 (arm64)

from jspaint.

exonjoe avatar exonjoe commented on May 24, 2024

Similar problem for me on macOS 12.7, Chrome 119.0.6045.123

But I noticed that:

  • Using the fill tool does not reset the canvas, except in Black and white mode
  • Using the free-form select or rectangle select tools:
    • Just moving the selection will NOT reset the canvas
    • Just resizing the selection WILL reset the canvas
    • Resizing and then moving the selection (without "applying" the resize first by clicking outside the selection) will NOT reset the canvas
  • Clicking and immediately releasing with the ellipse/rectangle/rounded-rectangle tools (i.e. without dragging into an actual shape) triggers the "Woah! / Your browser may have cleared the canvas due to memory usage" message.
  • This message is also triggered when using Image > Clear Image from the toolbar

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024

Similar problem for me on macOS 12.7, Chrome 119.0.6045.123

But I noticed that:

  • Using the fill tool does not reset the canvas, except in Black and white mode

  • Using the free-form select or rectangle select tools:

    • Just moving the selection will NOT reset the canvas
    • Just resizing the selection WILL reset the canvas
    • Resizing and then moving the selection (without "applying" the resize first by clicking outside the selection) will NOT reset the canvas
  • Clicking and immediately releasing with the ellipse/rectangle/rounded-rectangle tools (i.e. without dragging into an actual shape) triggers the "Woah! / Your browser may have cleared the canvas due to memory usage" message.

  • This message is also triggered when using Image > Clear Image from the toolbar

interesting, i think i recalled seeing that just moving a selected box will delete the area around it, but the selected stuff itself will be safe
i ended up recording what i did with the canvas since i don't know how to describe it

Untitled.mov

from jspaint.

1j01 avatar 1j01 commented on May 24, 2024

I made a tweaked test page, hopefully demonstrating the bug.
Let me know if this reproduces the bug, y'all. (I feel like it won't, since it's a shot in the dark, and the Chrome team ought to have automated tests for things like this, but still...)

@exonjoe

Using the fill tool does not reset the canvas, except in Black and white mode

In Black and White mode it renders the fill region to a separate canvas and then draws that canvas onto the main canvas, whereas in Color mode, it draws the fill directly onto the canvas. This explains the difference. Similarly...

Just moving the selection will NOT reset the canvas
Just resizing the selection WILL reset the canvas

Moving the selection doesn't use drawImage, but resizing the selection uses drawImage. Also, drawing with most of the tools uses drawImage when done.

Resizing and then moving the selection (without "applying" the resize first by clicking outside the selection) will NOT reset the canvas

This is curious. I'm not sure I can explain that. And, well, finalizing the selection also uses drawImage, so that somewhat muddles things.

from jspaint.

exonjoe avatar exonjoe commented on May 24, 2024

@1j01
I did some research into this myself, and it does definitely seem to be an issue with drawImage(). In fact, it seems to be something particular to passing an HTMLCanvasElement as the image parameter. I found that using an HTMLImageElement or OffscreenCanvas worked fine!

I was tinkering with tool.pointerup() at src/tools.js:1195, using the line tool to experiment. The existing line of code I was replacing is this one at line 1201:

main_ctx.drawImage(tool.shape_canvas, 0, 0);

If I create a dummy canvas element and draw to it as an intermediate step, I just get the same result as usual: each new line erases all existing canvas data. Here's the code for that:

// Dummy intermediate HTMLCanvasElement fails 🚫
const dummyCanvas = document.createElement("canvas");
dummyCanvas.height = tool.shape_canvas.height;
dummyCanvas.width = tool.shape_canvas.width;
const dummyCtx = dummyCanvas.getContext("2d");
dummyCtx.drawImage(tool.shape_canvas, 0, 0);
main_ctx.drawImage(dummyCanvas, 0, 0);
// main_ctx.drawImage(tool.shape_canvas, 0, 0);

However, if I do the same thing with an OffscreenCanvas, this fixes the issue and the line tool works as expected!

// Dummy intermediate OffscreenCanvas succeeds! ✅ 
const offscreenCanvas = new OffscreenCanvas(tool.shape_canvas.width, tool.shape_canvas.height);
const offscreenCtx = offscreenCanvas.getContext("2d");
offscreenCtx.drawImage(tool.shape_canvas, 0, 0);
main_ctx.drawImage(offscreenCanvas, 0, 0);
// main_ctx.drawImage(tool.shape_canvas, 0, 0);

I also did a version where I rendered the tool canvas to a blob, then put that in an HTMLImageElement and passed that to drawImage()... it's more complicated and maybe a little less performant, but it works too.

// Dummy intermediate HTMLImageElement succeeds! ✅ 
tool.shape_canvas.toBlob((blob) => {
  const newImg = document.createElement("img");
  const url = URL.createObjectURL(blob);
  
  newImg.onload = () => {
    URL.revokeObjectURL(url);
    main_ctx.drawImage(newImg, 0, 0);
    newImg.parentElement.removeChild(newImg);
  };
  
  newImg.src = url;
  
  tool.shape_canvas = null;
  document.body.appendChild(newImg);
});
// main_ctx.drawImage(tool.shape_canvas, 0, 0);

Okay, so the problem is with HTMLCanvasElements... is it all of them? I tried creating a dummy canvas element and drawing that instead of the actual tool canvas (similar to your test page) and it exhibits the problem too! This code will make a red square appear somewhere on the canvas every time you draw a line, but it clears the whole canvas each time too, so you only ever see up to 1 square:

// Dummy brand new, unrelated HTMLCanvasElement fails 🚫
const canvas = document.createElement("canvas");
canvas.width = tool.shape_canvas.width;
canvas.height = tool.shape_canvas.height;
const ctx = canvas.getContext("2d");
const x = Math.floor(Math.random()*100);
const y = Math.floor(Math.random()*100);
ctx.fillStyle = "rgb(200, 0, 0)";
ctx.fillRect(x, y, 50, 50);
main_ctx.drawImage(canvas, 0, 0);
// main_ctx.drawImage(tool.shape_canvas, 0, 0);

So it would seem that this behavior is happening with any HTMLCanvasElement... except, I tried one other thing, which was to render the main canvas to itself (using a small 10px offset so I can actually see something happening):

// Self-referential HTMLCanvasElement succeeds! ✅
main_ctx.drawImage(main_ctx.canvas, 10, 0);
// main_ctx.drawImage(tool.shape_canvas, 0, 0);

And in this case, the bug doesn't manifest—we are indeed rendering the main canvas on top of itself, without clearing it every time.

I have no idea why we would see the problem when using the tool canvas, or a fresh canvas, but not when using the main canvas. I also have no idea why the test page doesn't reproduce the bug.

Any ideas?

from jspaint.

jakub-g avatar jakub-g commented on May 24, 2024

Same issue on Chrome 119 / MacOS 13.6.

Luckily it works on Firefox (using Nightly 121) 🦊

from jspaint.

1j01 avatar 1j01 commented on May 24, 2024

@exonjoe Thank you for your research and clear breakdown!

I have no idea why we would see the problem when using the tool canvas, or a fresh canvas, but not when using the main canvas. I also have no idea why the test page doesn't reproduce the bug.

Any ideas?

Well it's natural that drawing a canvas to itself might behave differently as it's a special case. It probably needs to copy a region of the canvas before performing the operation, in case the source and destination regions overlap. Drawing an OffscreenCanvas also would need a different implementation under the hood, but it's good to know that this works.

As for the test case, what I want to know is:

  • Does the bug show up when loading JS Paint in an iframe? https://jsfiddle.net/1j01/t23hobw8/ (or https://98.js.org for that matter)
  • Does the bug show up when loading my test case without any iframes involved, if you save the following as an HTML file and open it?
<!doctype html>
<html>
	<head>
		<title>Bug Repo Attempt for jspaint issue #328</title>
	</head>
	<body>
		<canvas id="myCanvas" width="500" height="200"></canvas>
		<button onclick="hopefullyRepro()">Click me</button>
		<p>
			This should display purple squares with blue outlines on top of each other each time you click.
			If you see only one square "jumping around", it's broken, demonstrating the bug.
		</p>
		<a href="https://github.com/1j01/jspaint/issues/328">See JS Paint issue about this Chrome bug</a>
		<script>
			function hopefullyRepro()
			{
				const brushCanvas = document.createElement("canvas");
				const brushCtx = brushCanvas.getContext("2d");
				brushCtx.fillStyle = "blue";
				brushCtx.fillRect(10, 10, 10, 10);
				let x = ~~(Math.random() * 100);
				let y = ~~(Math.random() * 50);
				const imageData = brushCtx.getImageData(12, 12, 6, 6);
				for (let i=0; i<imageData.data.length; i+=4) {
					imageData.data[i] = 255;
				}
				brushCtx.putImageData(imageData, 12, 12);

				document.getElementById('myCanvas').getContext('2d').drawImage(brushCanvas, x, y);
			}
		</script>
		<style>
			button {
				font-size: 3em;
				display: block;
			}
		</style>
	</body>
</html>

from jspaint.

exonjoe avatar exonjoe commented on May 24, 2024

Yes, still seeing the bug in both the JSFiddle and 98.js :(

  • Does the bug show up when loading my test case without any iframes involved, if you save the following as an HTML file and open it?

Nah, the test case is still fine for me!

Doesn't seem like being in an iframe is making a difference...

One thing I just tried: I made a new dummy canvas (using your make_canvas function, to keep the dummy canvas as similar to the main canvas as possible) and added it to the document so I could see what's going on in it. I started drawing the tool.shape_canvas to it, while still also drawing to the main canvas. I did this to check whether the problem applied when writing to any canvas, or just the main canvas.

I also added debugger statements immediately before and after the main_ctx.drawImage() call to confirm that the bug happens during that call.

// Dummy canvas renders fine but main canvas doesn't 😖
if (!document.getElementById(`dummyCanvas`)) {
  const dummyCanvas = make_canvas(tool.shape_canvas.width, tool.shape_canvas.height);
  dummyCanvas.style.position = `fixed`;
  dummyCanvas.style.top = `0`;
  dummyCanvas.style.right = `0`;
  dummyCanvas.style.zIndex = `99999`;
  dummyCanvas.style.border = `2px solid red`;
  dummyCanvas.id = `dummyCanvas`;
  document.body.append(dummyCanvas);
}
const dummyCanvasActual = document.getElementById(`dummyCanvas`);
const dummyCtx = dummyCanvasActual.getContext("2d");
dummyCtx.drawImage(tool.shape_canvas, 0, 0);
debugger;
main_ctx.drawImage(tool.shape_canvas, 0, 0);
debugger;

In this video, we can see in the red box that the dummyCanvas behaves itself just fine. We can also see that the debugger statements coming either side of the main_ctx.drawImage() calls capture the "before and after" of the bug, as we see the main canvas being cleared between the two:

Screen.Recording.2023-11-18.at.7.57.31.PM.mov

So... is the main canvas being "corrupted" at some point, making it misbehave in a way that a fresh canvas doesn't? I did try checking the obvious suspects like the globalAlpha and globalCompositeOperation of the canvases, but they're identical...

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024

i wonder if there has been further updates since then…?
(no pressure! ^^;;)

from jspaint.

tempaccount9317 avatar tempaccount9317 commented on May 24, 2024

trying to read the comments over on the chromium forms gives me a bit of a headache

1j01:
Does this test page show multiple circles when you click it multiple times, or just one? I'm thinking this chromium bug could be the culprit.

1431968 and

boowangoo:
I reported this issue to Chromium, and it looks like they already have someone assigned.

1506384 (aka the post above) kinda describes the same situation though right?

from jspaint.

boowangoo avatar boowangoo commented on May 24, 2024

@tempaccount9317 I don't fully understand the bisect information either 😅. But 119 is the current stable build. So I focused on the first forward bisect information, which I'm guessing is to find the first breaking commit. Seems like the issue was traced to a commit (4881264) in September, and the owner already has a patch (5027957) for it. I'm guessing that the reverse bisects are to find the last working commit? If you read the description from 5027957, the author acknowledges that it fixes an bug from 4881264, which sounds like the bug that we are experiencing.

I just installed Chrome Beta, which is on build 120.0.6099.62 and already has that patch applied, and can confirm that the issue is not there. Seems like the bug will be resolved in the next stable update.

1431968 and 1506384 (aka the post above) kinda describes the same situation though right?

1431968 was reported on build 112 in April, and the team cannot reproduce it yet. So I'm inclined to believe that it's a separate issue, but I could be wrong.

from jspaint.

gth001 avatar gth001 commented on May 24, 2024

If you're using Apple Silicon M1 on a Chromium browser then it's a known bug in Chromium and the solution is chrome://flags/#disable-accelerated-2d-canvas via #328 (comment)

from jspaint.

boowangoo avatar boowangoo commented on May 24, 2024

As per the comment on this bug (1500272#c30), the fix has been merged and the stable build has been shipped.

I just updated Chrome and no longer see the bug on jspaint.

from jspaint.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.