Jaggies text when fillText in canvas in chrome

I am trying to draw text in a canvas, but the drawn text has jaggies, especially in chrome 31.0.1650. I tried -webkit-font-smoothing:antialiased,text-shadow , but all in vain.

How to solve this problem? Thanks in advance.

Here is the style code:

 <style> #my_canvas{ -webkit-font-smoothing: antialiased; text-shadow: 1px 1px 1px rgba(0,0,0,0.004); text-indent: -9999px; } </style> 

Code in body:

 <canvas id="my_canvas" height="300" width="2200"></canvas> <script> var canvas = document.getElementById("my_canvas"); var context = canvas.getContext("2d"); context.imageSmoothingEnabled =true; context.fillStyle = "BLACK"; context.font = "bold 100px Arial"; context.fillText("A quick brown fox jumps over the lazy dOg", 50, 200); </script> 
+1
source share
1 answer

This is a problem with the Chrome engine.

There is a technique you can use to get around this:

  • Customize the screen canvas with twice the size of the screen canvas
  • Draw the text on the screen canvas to scale: font size and position
  • Draw a screen canvas on the main canvas, zoomed out (in this case, half).

Live demo here

The difference is subtle (as expected), but improves quality. Here is the extension:

Compare

Sidenotes: CSS does not affect the contents of the canvas, but only on the elements. Image anti-aliasing is enabled by default and affects only images, but not text or shapes (we will use this, although for this technique).

 var scale = 2; // scale everything x2. var ocanvas = document.createElement('canvas'); var octx = ocanvas.getContext('2d'); ocanvas.width = canvas.width * scale; // set the size of new canvas ocanvas.height = canvas.height * scale; // draw the text to off-screen canvas instead at double sizes octx.fillStyle = "BLACK"; octx.font = "bold " + (100 * scale) + "px Arial"; octx.fillText("A quick brown fox jumps over the lazy dOg", 50*scale, 200*scale); // key step is to draw the off-screen canvas to main canvas context.drawImage(ocanvas, 0, 0, canvas.width, canvas.height); 

What happens, here we introduce interpolation in the mix. Chrome will draw text very roughly and on a screen canvas, but after the text becomes rasterized, we can process it as an image.

When we draw the canvas (aka image) on our main canvas half the size, interpolation (sub-sampling) is triggered and will be a low-pass filter with pixels, giving a smoother look.

This, of course, will take more memory, but if the result is important, this is a small price to pay for now.

You will probably notice that values ​​other than 2 do not work as well. This is because the canvas usually uses bilinear interpolation rather than bi-cubic (which would allow us to use 4). But I think 2x helps us well in this case.

Why not use a transform i.e. scale() ? The Chrome text engine (or how to use it) does not rasterize the text to 1x, and then converts it. It takes vectors, converts them, and then rasterizes the text, which will give the same result (i.e. Scale 0.5, draw double).

+2
source

All Articles