比较HTML5 Canvas中的两种字体

Comparing two fonts in HTML5 Canvas

本文关键字:两种 字体 HTML5 Canvas 比较      更新时间:2023-09-26

我试图把一个工具,检查一个给定的字符是否显示在指定的样式字体或系统默认字体。我的最终目标是能够检查,至少在现代(阅读:IE8+)浏览器中,是否在给定的字体中支持连接。

我有两个画布显示相同的结扎(在本例中,st)。我将这些画布转换为数据并比较它们以查看字符是否匹配。

Arial(像大多数字体一样)没有st字形,所以它退回到默认的衬线字体。奇怪的是:虽然它们显示相同的字体,但两个画布没有相同的数据

为什么?因为它们在画布上的位置并不完全相同。我猜这与字体的相对高度不同有关(一个比另一个略高,尽管字体不同)。这种差异似乎只有一两个像素,而且不同的字体也不同。

如何解决这个问题?我目前唯一的想法是找到一种方法来测量字体的高度,并相应地调整其位置,但我不知道如何做到这一点,不幸的是。还有其他方法可以让这两个图像完全相同吗?

您可以看到下面的代码。两个画布都被成功初始化并附加到元素的主体中,这样我就可以在视觉上看到发生了什么(尽管这在我正在处理的实际脚本中是不必要的)。我已经删除了初始化和上下文,因为它们都工作得很好。

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;
}

所以我正确地理解了这个问题,问题是一个画布指定Arial(但回落到衬线字体),另一个是衬线字体,当你做像素匹配时,它不是一个匹配,因为其中一个有轻微的偏移?

一个建议是从每个画布上抓取一个参考像素,并比较两个参考像素的位置以获得偏移量。然后将偏移量考虑到比较循环中。

例如,在这种情况下,你可以从画布的左上角开始检查像素,然后在该列中向下扫描,当你到达底部时,回到下一列的顶部并向下扫描。

一旦你击中一个像素,不是你的背景的颜色,记录的位置,并使用它作为参考像素。这应该是你的字体的边缘。对下一个画布做同样的操作,然后比较两个参考像素的位置以获得偏移量。在你的比较循环中把这个偏移量考虑进去。

希望我有正确的想法的问题,我希望这有助于!