I'm trying to put together a tool that checks whether a given character is displayed in the specified style font or a system default font. My ultimate goal is to be able to check, at least in modern (read: IE8+) browsers, whether a ligature is supported in a given font.
I've got two canvases displaying the same ligature (in this case, st). I turn those canvases into data and compare them to see if the characters match.
Arial (like most fonts) does not have an st ligature, so it falls back to the default serif font. Here's where it gets weird: although they're displaying the same font, the two canvases don't have the same data.
Why? Because their positions on the canvas aren't exactly the same. I'm guessing it has something to do with the different relative heights of the fonts (one is slightly taller than the other, though which varies font to font). The difference appears to be one of a pixel or two, and it varies font by font.
How might one go about solving this? My only current idea is finding a way to measure the height of the font and adjusting its position accordingly, but I have no idea how to do that, unfortunately. Are there other approaches I might take to make the two images identical?
You can see the code below. Both canvases are successfully initialized and appended to the body of the element so I can see what's going on visually (though that's not necessary in the actual script I'm working on). I've dropped the initialization and context, as those are all working just fine.
function checkLig() {
lig = 'fb06' // this is the unicode for the st ligature
canvas0.width = 250;
canvas0.height = 50;
context0.fillStyle = 'rgb(0, 0, 0)';
context0.textBaseline = 'top';
context0.font = 'normal normal normal 40px Arial';
context0.fillText(String.fromCharCode(parseInt(lig, 16)), 0, 0);
var print0 = context0.getImageData(0, 0, 720, 50).data;
canvas1.width = 250;
canvas1.height = 50;
context1.fillStyle = 'rgb(0, 0, 0)';
context1.textBaseline = 'top';
context1.font = 'normal normal normal 40px serif';
context1.fillText(String.fromCharCode(parseInt(lig, 16)), 0, 0);
var print1 = context1.getImageData(0, 0, 720, 50).data;
var i = 0, same = true, len = 720 * 50 * 4;
while (i < len && same === true) {
if (print0[i] !== print1[i]) {
same = false;
}
else {
i++;
}
}
return same;
}