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

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

Раздел system-ui спецификации модуля CSS Fonts 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 теперь имеет больше переменных настроек : оптический размер и две уникальные настройки веса:

Мохаве
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 . В то время как system-ui в Catalina — это переменный шрифт с настройками 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 с некоторыми другими забавными настройками 👍

Детская площадка

Нажмите «Ремикс для редактирования в сбое» ниже, чтобы получить редактируемую копию сбоя, а затем отредактируйте новые параметры font-variation-settings чтобы увидеть, как это повлияет на ваш шрифт. Помните, что этот глюк будет работать только в том случае, если вы используете устройство macOS Catalina.

В macOS 10.15 к системному шрифту добавлены новые функции, а в 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 использовала «Текст Сан-Франциско». Когда размер текста составлял 20px и более, macOS использовала «Дисплей Сан-Франциско». Оптические размеры были встроены статически в два отдельных шрифта.

Catalina (macOS 10.15) выпустила новый единый вариативный шрифт для Сан-Франциско. Больше не нужно управлять «Текстом» и «Дисплей». Он также получил новый вариант настройки 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 по-прежнему поддерживает ее. 11 октября шрифты «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 не могли «просто вернуться», чтобы решить проблему. Инженеры Chromium также попытались использовать другой флаг сборки для изменения кодового пути, связанного со шрифтами, в Skia, что решило проблему с жирными шрифтами, но устранило проблему с пробелами.

Исправление

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

Отображение system-ui, всей его толщины и вариантов шрифта в списке. Половина, которая раньше не работала, теперь выглядит великолепно.

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