Sub-pixel rendering in Chrome Canvas

Viewed 4674

I'm wondering if anyone knows if it's possible to enable sub-pixel rendering in an HTML5 canvas in Chrome (and/or Safari).

Chrome does sub-pixel rendering in HTML, and FF does it for both HTML & Canvas rendering. Specific issue pictured below:

Screenshot

4 Answers

It is possible, depending on the platform. Here is how to do it:

  1. Create an opaque canvas context, with canvas.getContext('2d', {alpha: false})
  2. Set the -webkit-font-smoothing property to the value you want: auto, antialias (blur), subpixel-antialias ("LCD" text with color fringe) or none.

This will apply to all of the text in the canvas.

Here's a screenshot from Chrome 81 on Mac; the text in the green rectangle is canvas fillText:

Screenshot of canvas text with different antialiasing options

Here is the source of this file:


<!DOCTYPE html>
<style>
canvas {
  border: 1px solid green;
}
div {
  position: float;
  float: left;
}
#a {
  -webkit-font-smoothing: auto;
}
#b {
  -webkit-font-smoothing: antialiased;
}
#c {
  -webkit-font-smoothing: subpixel-antialiased;
}
#d {
  -webkit-font-smoothing: none;
}
</style>
<div id="a">
(auto)<br>
??????????<br>
||||||||||<br>
IIIIIIIIII<br>
llllllllll<br>
//////////<br>
</div>
<div id="b">
(antialiased)<br>
??????????<br>
||||||||||<br>
IIIIIIIIII<br>
llllllllll<br>
//////////<br>
</div>
<div id="c">
(subpixel)<br>
??????????<br>
||||||||||<br>
IIIIIIIIII<br>
llllllllll<br>
//////////<br>
</div>
<div id="d">
(none)<br>
??????????<br>
||||||||||<br>
IIIIIIIIII<br>
llllllllll<br>
//////////<br>
</div>
<script>
'use strict';
function add(container) {
  let canvas = document.createElement('canvas');
  const width = container.clientWidth;
  canvas.style.width = `${width}px`;
  const height = 40;
  canvas.style.height = `${height}px`;
  canvas.width = Math.floor(width * window.devicePixelRatio);
  canvas.height = Math.floor(height * window.devicePixelRatio);
  container.append(canvas);
  let ctx = canvas.getContext('2d', {alpha: false});
  ctx.fillStyle = 'white';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = 'black';
  ctx.font = '12pt Arial';
  ctx.fillText('\/!|hello world', 0, height / 2);
}

add(a);
add(b);
add(c);
add(d);
</script>
Related