Дополнительные варианты переменных шрифтов для шрифта system-ui macOS в Chromium 83

Catalina добавляет в macOS новый единый переменный системный шрифт.

Доминик Рётчес
Dominik Röttsches

Раздел «system-ui» спецификации CSS Fonts Module Level 4 определяет ключевое слово шрифта system-ui , которое позволяет разработчикам использовать встроенный, оптимизированный для турбонаддува, локализованный, высококачественный, не требующий загрузки шрифт операционной системы по умолчанию прямо на своих сайтах и ​​в приложениях.

body {
  font-family: system-ui;
}

Такой выбор типографики равносилен высказыванию «использовать системный шрифт по умолчанию для текущего местоположения этого пользователя».

В macOS system-ui является San Francisco — шрифт, который команда дизайнеров проверила, протестировала и… недавно обновила! Сначала мы рассмотрим новые интересные функции вариативных шрифтов в Catalina , а затем рассмотрим несколько ошибок и то, как их решили инженеры Chromium .

В этой статье предполагается, что вы уже знакомы с вариативными шрифтами. Если нет, ознакомьтесь со статьей «Введение в вариативные шрифты в интернете» и видео ниже.

Совместимость с браузерами

На момент написания статьи system-ui поддерживается в Chromium (с версии 56), Edge (с версии 79), Safari (с версии 11) и Firefox (с версии 43), но с ключевым словом -apple-system . Обновления см. в разделе «Можно ли использовать переменные шрифты?» .

Новые полномочия

Новые возможности, которые Catalina привнесла в системный шрифт, теперь доступны веб-разработчикам, начиная с Chromium 83. Шрифт system-ui теперь имеет больше переменных настроек : оптическое изменение размера и 2 уникальные настройки насыщенности:

Мохаве
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750
  ;
}
Каталина
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750,
    'opsz' 20,
    'GRAD' 400,
    'YAXS' 400
  ;
}

В Mojave system-ui — это вариативный шрифт с настройками только wght . В Catalina system-ui — это вариативный шрифт с настройками wght , opsz , GRAD и YAXS .

Мне кажется, это несколько интересных возможностей для прогрессивного улучшения дизайна! Если хотите, действительно изучите тонкости системного шрифта.

wght

Принимает толщину шрифта от 0 до 900 и применяется одинаково ко всем символам.

/* 0-900 */
font-variation-settings: 'wght' 750;

opsz

Оптическая калибровка похожа на кернинг или межбуквенный интервал, но интервал определяется человеческим глазом, а не математически. Значение 19 и ниже предназначено для интервала в тексте и основном тексте, а значение 20 и выше — для интервала в заголовках и названиях.

/* 19 or 20 */
font-variation-settings: 'opsz' 20;

GRAD

Аналогично весу, но без учёта горизонтального интервала. Принимает значения от 400 до 1000 .

/* 400-1000 */
font-variation-settings: 'GRAD' 500;

YAXS

Растягивает глиф по вертикали. Принимает значения от 400 до 1000 .

/* 400-1000 */
font-variation-settings: 'YAXS' 500;

Комбинирование вариантов

С помощью нескольких строк CSS мы можем изменить настройки шрифта, установив жирный шрифт по своему выбору или попробовать другие интересные комбинации:

font-weight: 700;
font-weight: bold;
font-variation-settings: 'wght' 750, 'YAXS' 600, 'GRAD' 500, 'opsz' 20;

И вот так пользователи Chromium на macOS видят ваш обновленный, индивидуальный вес 750 с некоторыми другими интересными изменениями 👍

В macOS 10.15 появились новые функции системного шрифта, а в системе отслеживания ошибок Chromium была зафиксирована сложная ошибка system-ui интерфейса. Интересно, связаны ли они между собой?

Приложение: Регрессия system-ui

Эта история начинается с другой ошибки: #1005969 . Она была обнаружена в macOS 10.15, поскольку интервал между шрифтами system-ui выглядел узким и перегруженным.

Сравнение двух абзацев со страницы группы в Facebook. Слева — Chrome, справа — Safari. В Chrome акцент сделан менее заметным, но интервалы немного плотнее.
Chrome слева (более точное отслеживание), Safari справа (лучшее оптическое расстояние)

Фон

Вы когда-нибудь замечали, как в macOS 10.14 ваши абзацы или заголовки «привязываются» к другому шрифту при увеличении или уменьшении размера?

В Mojave (macOS 10.14) шрифт system-ui переключался между двумя шрифтами в зависимости от целевого размера. При размере текста менее 20px macOS использовала шрифт «San Francisco Text». При размере текста 20px и более macOS использовала шрифт «San Francisco Display». Оптическое изменение размера было статически реализовано в двух отдельных шрифтах.

В Catalina (macOS 10.15) появился новый объединённый вариативный шрифт для San Francisco. Больше нет необходимости управлять разделами «Текст» и «Отображение». Также появилась новая настройка вариаций opsz описанная ранее.

h1 {
  font-variation-settings: 'opsz' 20;
}

К сожалению, значение opsz по умолчанию в новом шрифте Catalina равно 20 , и разработчики Chromium не были готовы применить opsz к системному шрифту. Это привело к тому, что шрифты меньшего размера отображались слишком узко.

Чтобы исправить это, Chromium нужно было правильно применить opsz к системному шрифту. Это привело к исправлению ошибки № 1005969. Победа! Или…?

Пока не сделано

Вот тут-то и возникла сложность: Chromium применил opsz но что-то всё равно выглядело не так. Системные шрифты на Mac имеют дополнительную таблицу шрифтов trak , которая корректирует горизонтальный интервал. Работая над исправлением, инженеры Chromium заметили, что в macOS при получении горизонтальных метрик из объекта CTFontRef метрики trak уже учитывались в результатах. Библиотеке формирования шрифтов Chromium HarfBuzz нужны метрики, в которых значения trak ещё не учитываются.

Отображение системного интерфейса со всеми его начертаниями и вариациями в виде списка. Половина из них не имеет различий в начертании.
Слева: жирный шрифт применяется к размерам шрифта 19 и меньше. Справа: шрифты размером 20 и больше теряют жирный стиль.

Skia (графическая библиотека, а не одноимённый шрифт) использует как класс CGFontRef из CoreGraphics , так и класс CTFontRef из CoreText . Из-за необходимости внутренних преобразований между этими объектами (используемых для обеспечения обратной совместимости и доступа к необходимым API обоих классов) при определённых обстоятельствах Skia теряла информацию о весе, и полужирные шрифты переставали работать. Это было отмечено в проблеме № 1057654 .

Skia по-прежнему должна поддерживать macOS 10.11, поскольку Chromium её всё ещё поддерживает. В версии 10.11 шрифты «San Francisco Text» и «San Francisco Display» даже не были вариативными. Каждый из них представлял собой семейство отдельных шрифтов для каждой доступной насыщенности. В какой-то момент их идентификаторы глифов рассинхронизировались. Поэтому, если Skia формировала текст (преобразовывала текст в глифы, которые можно было бы отобразить) с помощью «San Francisco Text», то при отображении с помощью «San Francisco Display» это была бы полная ерунда, и наоборот. И даже если Skia просто запросит другой размер, macOS может переключиться на другой. Должно быть возможно всегда использовать один из шрифтов и просто масштабировать его (используя матрицу для увеличения вместо запроса большего размера), но у CoreText есть проблема: он не увеличивает (только уменьшает) глифы sbix (цветные эмодзи). Всё немного сложнее. Похоже, CoreText ограничивает вертикальный размер после применения матрицы, что, по-видимому, связано с тем, что он не может отображать эмодзи под углом 45 градусов. В любом случае, если вы хотите, чтобы ваши эмодзи отображались крупными, вам нужно сделать копию шрифта для получения увеличенной версии.

Итак, чтобы создать копии объектов CTFont разных размеров внутри себя, гарантируя при этом использование одних и тех же базовых данных шрифта, Chromium извлек CGFont из CTFont , а затем создал новый CTFont из CGFont (объекты CGFont не зависят от размера, магическое переключение происходит на уровне CoreText ). Это работало нормально до версии 10.154. В 10.15 этот цикл обработки закончился потерей слишком большого количества информации, что привело к проблеме с весом. Flutter заметил проблему с весом , и было сделано альтернативное исправление для изменения размера, чтобы создавать новый CTFont непосредственно из исходного CTFont , управляя оптическим размером напрямую с помощью старого, но недокументированного атрибута в CoreText . Это поддерживает работу в 10.11 и устраняет другие проблемы (например, явную установку оптического размера на значение по умолчанию).

Однако это сохраняет большую часть «магии» CoreText в шрифте. Похоже, одна из причин заключается в том, что он всё же каким-то образом корректирует перемещение глифов, помимо таблицы trak (применение которой Chromium уже пытался подавить с помощью ещё одного недокументированного атрибута).

CGFont не делает ничего из этого «волшебства», так что, возможно, Chromium мог бы отделить CGFont от CTFont и просто использовать его для получения улучшений? К сожалению, это не сработает, поскольку CoreText известен тем, что изменяет шрифты и другими способами. Например, он делает маленькие эмодзи чуть больше, чем вы запросили (немного увеличивая их размер). CGFont об этом не знает, поэтому ваши эмодзи на основе sbix окажутся слишком близко друг к другу, поскольку вы будете использовать один размер, а CoreText будет отображать их немного крупнее. Chromium действительно нужны улучшения CTFont , но без отслеживания, и желательно без каких-либо других манипуляций.

Поскольку для исправления проблемы с пробелами требовался набор взаимосвязанных исправлений Blink и Skia, инженеры Chromium не могли просто вернуться к предыдущей версии, чтобы исправить проблему. Они также попробовали использовать другой флаг сборки для изменения кодового пути, связанного со шрифтами, в Skia, что решило проблему с жирным шрифтом, но ухудшило проблему с пробелами.

Исправление

В конце концов, Chromium, конечно же, решил исправить и то, и другое. Теперь Chromium использует встроенные функции HarfBuzz для измерения метрик шрифтов OpenType, чтобы получать горизонтальные метрики непосредственно из двоичных данных в системных таблицах шрифтов. Благодаря этому Chromium обходит CoreText и Skia, когда у шрифта есть таблица trak (за исключением случаев, когда это шрифт эмодзи).

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

В то же время все еще существует проблема Skia #10123, требующая отслеживания полного исправления этой проблемы в Skia и возврата к использованию Skia для извлечения метрик системных шрифтов оттуда вместо текущего исправления, которое выполняется через HarfBuzz .