This issue pertains to the text engine in Chrome.
Fortunately, there is a workaround solution available:
- Create an off-screen canvas that is double the size of the on-screen canvas
- Render the text onto the off-screen canvas using the appropriate scaling for font size and position
- Display the off-screen canvas on the main canvas at a scaled-down size (half in this instance)
The difference may be subtle, but it ultimately enhances the quality. Here's an enlarged view:
Keep in mind, CSS does not impact the content within the canvas, only its elements. Image smoothing is automatically enabled and specifically affects images, not text or shapes (although we will utilize this feature for this technique).
var scale = 2; // scale everything by x2.
var ocanvas = document.createElement('canvas');
var octx = ocanvas.getContext('2d');
ocanvas.width = canvas.width * scale; // define new canvas size
ocanvas.height = canvas.height * scale;
// render the text on the off-screen canvas 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);
// crucial step: draw the off-screen canvas on the main canvas
context.drawImage(ocanvas, 0, 0, canvas.width, canvas.height);
By introducing interpolation into the process, Chrome initially renders the text roughly, then rasterizes it for further manipulation as an image.
When displaying the canvas (i.e., image) on our primary canvas at half the size, interpolation (sub-sampling) activates to apply a low-pass filter on pixels, resulting in a smoother appearance.
While this method may require more memory usage, the improved outcome justifies the minor sacrifice.
You may observe better results with a scale value of 2 rather than other figures due to the canvas' use of bi-linear interpolation instead of bi-cubic.
Why not implement transform like scale()
? Chrome’s text rendering process transforms the vectors before rasterizing the text, achieving the same effect as scaling down after rendering at twice the size.