Firefox рендеринг шрифта OpenType не соответствует спецификации шрифта

Я загружаю веб-шрифт OpenType Open Sans через Google Fonts API / CSS.

Как в Chrome 43 (Linux+Windows), так и в Internet Explorer 11 (Windows) браузер отображает текст в точности так, как указано в шрифте. Однако в Firefox 38.0.5 ширина текста и / или интервал отображаются для некоторых символов по-разному. Все варианты шрифтов имеют значение по умолчанию ("нормальный").

В качестве примера мы можем использовать символы 1, a, b, а также i, "SansPerEm" для Open Sans равен 2048. Следовательно, при размере шрифта 18,0 пикселей ширина 30 символов каждого из указанных выше символов должна быть следующей на основе 1/u * p * c * w, где u = 2048, p = 18,0, с = 30, а w - ширина продвижения каждого символа ( уравнение Вольфрама Альфа).

+ ---------------------------------------- + -------- --- +
| символ | шрифт (px) | numChars | заранее | ширина (px) |
+------+----------+----------+-----------+-----------+
|  1   |   18,0   |    30    |   1171    |  308,76   |   
| а | 18,0   |    30    |   1139    |  300,322  |
| б | 18,0   |    30    |   1255    |  330,908  |
| я | 18,0   |    30    |   518     |  136,582  |
+----------------------------------------+-----------+

Это ( JSFiddle) использует метод canvas measureText вывести ширину в пикселях по 30 символов каждого из 1, a, b, а также i,

Длина текста Chrome точно соответствует ожидаемым значениям:

Хромированная ширина

Длина текста в Firefox Linux не соответствует ни одному из символов, кроме a даже после учета того факта, что Firefox не обеспечивает субпиксельной точности:

Firefox Linux ширины

Я подтвердил, что ширина, указанная в canvas, - это действительно то, что выводится как Chrome, так и Firefox - на следующем изображении показан красный фон с текстом Chrome в черном и текстом Firefox в белом - значения ширины соответствуют вышеприведенным в соответствии инструмент Gimp "Measure". Фирефокса b а также i слишком широк, и 1 слишком узкий

Сравнение Chrome / Firefox

Кроме того, длина текста в Firefox Windows даже не соответствует Firefox Linux - a а также b ширина теперь, как и ожидалось, но 1 а также i все еще неверны:

Firefox Windows ширины

Это чистый профиль Firefox с настройками по умолчанию и без установленных расширений.

Может кто-нибудь объяснить, что происходит, и как заставить Firefox отображать шрифт в соответствии со спецификацией шрифта?

ОБНОВЛЕНИЕ: В Windows, настройка предпочтений gfx.font_rendering.directwrite.enabled в true устраняет проблему (которую я считаю Firefox по умолчанию, когда доступно аппаратное ускорение, этот параметр просто включает его, даже если аппаратное ускорение недоступно, например, в моей тестовой системе VMWare). DirectWrite используется по умолчанию в Chrome для Windows начиная с версии 37. Поведение Linux до сих пор не объяснено. Этот пост в блоге объясняет больше о визуализации DirectWrite в Firefox на Windows.

1 ответ

Решение

(Этот ответ суммирует основные вопросы, поднятые в комментариях к вопросу, а также ряд дополнительных исследований, проведенных после того, как вопрос был опубликован.)

По разным и сложным причинам не все комбинации размеров браузера / ОС / размера шрифта отображаются на экране одинаково и не всегда соответствуют спецификациям шрифта. Поэтому, как правило, приложения должны создаваться таким образом, чтобы не требовалось идеальное позиционирование текста.

Субпиксельная конфигурация рендеринга текста

Некоторые комментарии по настройке определенных комбинаций браузера / ОС для поддержки субпиксельного рендеринга текста:

Windows

  • Браузеры, которые поддерживают и включают DirectWrite (в отличие от более старого метода GDI), как правило, поддерживают линейное, не намекаемое, субпиксельное позиционирование текста и, следовательно, способны (и обычно делают) следовать спецификациям ширины продвижения шрифта. Это включает в себя Chrome 37+ и Firefox 4+.
    • Firefox отключает DirectWrite по умолчанию, когда аппаратное ускорение недоступно, но его можно включить, установив свойство config gfx.font_rendering.directwrite.enabled в true,
    • Chrome 37+ DirectWrite включен по умолчанию, но его можно отключить, установив флаг Disable DirectWrite,
    • Internet Explorer (9+?) DirectWrite включен по умолчанию, но его можно отключить, установив режим совместимости.

Linux

Сконфигурируйте свой дисплей для сглаживания и субпиксельного рендеринга текста, настроив fontconfig для субпиксельного рендеринга (обычно через настройки дисплеев Gnome или KDE, но это можно сделать вручную через конфигурационные файлы fontconfig), установив freetype-freeworld (freetype с не бесплатная поддержка рендеринга субпикселей) и добавление Xft.lcdfilter: lcddefault в ~/.Xresources для приложений без поддержки fontconfig. Установите правильный тип субпиксельного рендеринга в зависимости от типа вашего ЖК-дисплея.

  • Поведение браузера кажется непоследовательным, даже если базовый дисплей поддерживает и настроен для субпиксельного рендеринга.
    • Последние версии Chrome (44 протестированных), по-видимому, поддерживают линейное позиционирование текста без намеков на субпиксели и, следовательно, в целом соответствуют спецификациям шрифта. Протестировано на KDE 4.14 с поддержкой рендеринга субпиксельного текста RGB.
    • Firefox (протестированный 38.0.5), по-видимому, выполняет нелинейное позиционирование с подсказками, поэтому не соответствует спецификациям шрифта, даже если дисплей настроен для субпиксельного рендеринга. Я не определил способ заставить Firefox использовать субпиксельный рендеринг текста.

Mac OS X

Информации для этой платформы пока нет.

Пиксельное идеальное позиционирование

Если, несмотря на трудности, создается приложение, которое требует точного позиционирования и проверки текста с точностью до пикселя, то обычно есть два способа сделать это:

1) Измерение ширины / высоты текста на основе холста или DOM: см. Расчет ширины текста с помощью JavaScript. Смотрите также Font.js Майка Камерманса (Pomax).

2) Использование OpenType.js для определения размеров текста из исходного шрифта, который работает быстрее, чем метод, описанный выше, но работает не во всех случаях.

Другие вопросы по тегам