Doubled canvas drawings on Android with hardware acceleration enabled

There is a bug in HTML 5 Canvas object exposed on Android platforms, in versions 4.1.1 till 4.3 (newest, as of writing it, though not yet fixed). It causes that, when hardware acceleration is turned on, any drawings on canvas will be doubled at top of the page.

At first, I thought, that this is caused only in Segment Display — a fabulous JS library, that I use. This is why, you’ll find a lot of references to it in this article. But then it turned out to be general Android problem, that appears not only in PhoneGap applications (which uses webview), but also in all pages served on Android 4.1.x+ platform.

So, you’ll also find some ideas, how to work around this problem, if you’re not using Segment Display.

First, summary of what I’ve found:

1. This is general bug found in HTML 5 on-board Android platform starting from version 4.1.1 and not fixed until version 4.3.

2. It only appears, when you have hardware acceleration enabled and it is gone, if you enable software acceleration. But this is not a factor, as most users would like to have it enabled. Hardware acceleration improves graphical operations on mobile devices significantly.

3. It appears mostly in PhoneGap applications, which are using webview (and therefore HTML5 Canvas), but it may also appear in simple pages served on these platforms.

There are few ways, you can solve it.

1. If you’re library or widget author having this issue in your own code or your skills allows you to do hard code modifications, consider implementing “hack” with redrawing canvas, explained in this Stack Overflow answer.

2. Same as above. I’m using Segment Display, which is also affected by this bug. Library’s author told me to add these two lines:

context.fillStyle = '#fff';
context.fillRect(0, 0, display.width, display.height);

right after this line:

// clear canvas
context.clearRect(0, 0, display.width, display.height);

So, from a quick analysis of given code I assume that a transparent (clearRect) canvas is causing these problems and changing it to non-transparent one (fillRect) fixes the bug. If you have enough skills, consider implementing same or similar solution in your code.

3. Problem does not exists, if your canvas or its container has width of 256px or smaller. If you can make it at most that long, this is the quickest solution.

4. Bug does not appears, if canvas, container or any parent hasn’t got overflow-x, overflow-y or overflow set to hidden, auto or scroll. If you can set these CSS attributes to display for canvas, its container and all parent objects, then this is another quick fix.

5. If you’re Segment Display user or you’re using / developing similar library, consider implementing solution provided by Segment Display’s author of prefixing canvas background to certain color:

// clear canvas
context.clearRect(0, 0, display.width, display.height);
context.fillStyle = '#fff';
context.fillRect(0, 0, display.width, display.height);

I hope that all solutions might be treaten as temporary and that this bug will finally be solved on system side. It concerns me much, that it hasn’t been solved yet, though we have four general system updates by that time. But, what we can do? For current moment we have only above hacks and workarounds.

Leave a Reply