1

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

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

Arial(像大多数字体一样)没有 st 连字,因此它回退到默认的 serif 字体。这就是奇怪的地方:虽然它们显示相同的字体,但两个画布没有相同的数据

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

如何解决这个问题?我目前唯一的想法是找到一种方法来测量字体的高度并相应地调整其位置,但不幸的是我不知道该怎么做。我是否可以采取其他方法使这两个图像相同?

你可以看到下面的代码。两个画布都已成功初始化并附加到元素的主体,因此我可以直观地看到正在发生的事情(尽管在我正在处理的实际脚本中这不是必需的)。我已经放弃了初始化和上下文,因为它们都工作得很好。

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

1 回答 1

2

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

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

例如,在这种情况下,您可以通过从一个画布的左上角开始检查像素并在该列中向下扫描来获取参考像素,当您到达底部时,返回到下一列的顶部并向下扫描.

一旦你击中了一个不是背景颜色的像素,请记录该位置并将其用作参考像素。那应该是字体的边缘。对下一个画布执行相同操作,然后比较两个参考像素的位置以获得偏移。在比较循环中考虑该偏移量。

希望我对问题有正确的认识,希望对您有所帮助!

于 2011-10-21T12:28:33.487 回答