我正在尝试组装一个工具来检查给定字符是以指定样式字体还是以系统默认字体显示。我的最终目标是至少在现代(阅读:IE8+)浏览器中能够检查给定字体是否支持连字。
我有两个 Canvas 显示相同的连字(在本例中为 st)。我将这些 Canvas 转换为数据并比较它们以查看字符是否匹配。
Arial(与大多数字体一样)没有 st 连字,因此它会退回到默认的衬线字体。这就是奇怪的地方:虽然它们显示相同的字体,但两个 Canvas 没有相同的数据。
为什么?因为它们在 Canvas 上的位置并不完全相同。我猜这与字体的不同相对高度有关(一个比另一个略高,尽管字体因字体而异)。差异似乎只有一两个像素,并且因字体而异。
如何解决这个问题?我目前唯一的想法是找到一种方法来测量字体的高度并相应地调整其位置,但不幸的是我不知道该怎么做。我是否可以采取其他方法使两张图片完全相同?
你可以看到下面的代码。两个 Canvas 都已成功初始化并附加到元素的主体,因此我可以直观地看到发生了什么(尽管在我正在处理的实际脚本中这不是必需的)。我已经删除了初始化和上下文,因为它们都工作得很好。
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;
}
最佳答案
所以我正确地理解了这个问题,问题是一个 Canvas 指定了 Arial(但回落到 Serif),另一个是 Serif,当你进行像素匹配时,它不匹配,因为其中一个有轻微的偏移量?
一个建议是从每个 Canvas 上抓取一个引用像素并比较两个引用像素的位置以获得偏移量。然后将该偏移量计入您的比较循环。
例如,在这种情况下,您可以通过从一个 Canvas 的左上角开始检查像素并向下扫描该列来获取引用像素,当您到达底部时,返回到下一列的顶部并向下扫描。
一旦您碰到一个不是背景颜色的像素,请记录该位置并将其用作您的引用像素。那应该是你字体的边缘。 对下一个 Canvas 执行相同操作,然后比较两个引用像素的位置以获得偏移量。在比较循环中考虑该偏移量。
希望我对问题的理解是正确的,希望对您有所帮助!
关于javascript - 比较 HTML5 Canvas 中的两种字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7844491/