Сравнение двух шрифтов в HTML5 Canvas - PullRequest
1 голос
/ 21 октября 2011

Я пытаюсь собрать инструмент, который проверяет, отображается ли данный символ шрифтом указанного стиля или системным шрифтом по умолчанию.Моя конечная цель - проверить, по крайней мере, в современных браузерах (читай: IE8 +), поддерживается ли лигатура заданным шрифтом.

У меня есть два полотна с одинаковой лигатурой (в этомдело, ст).Я превращаю эти холсты в данные и сравниваю их, чтобы увидеть, совпадают ли символы.

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

1 Ответ

2 голосов
/ 21 октября 2011

Так что я правильно понимаю вопрос, проблема в том, что один холст задает Arial (но возвращается к Serif), а другой - Serif, и когда вы делаете сопоставление пикселей, это не совпадает, потому что один из них имеет небольшоеoffset?

Одно из предложений состоит в том, чтобы взять опорный пиксель с каждого холста и сравнить положения двух опорных пикселей, чтобы получить смещение.А затем включите это смещение в ваш цикл сравнения.

Например, в этом случае вы можете получить эталонный пиксель, начав проверять пиксели в верхнем левом углу одного холста и сканируя вниз в этом столбце и когдадойдите до дна, вернитесь к вершине следующего столбца и отсканируйте.

1006 * Как только вы нажмете пиксель, который не цвет фона, записать позицию и использовать его в качестве опорного пикселя.Это должно быть краем вашего шрифта.Сделайте то же самое со следующим холстом, а затем сравните положения двух опорных пикселей, чтобы получить смещение.Учитывайте это смещение в цикле сравнения.

Надеюсь, у меня есть правильное представление о проблеме, и я надеюсь, что это поможет!

...