Перейти к содержимому

Блог

Шрифты выдают систему дважды: список и родовое семейство

Профиль объявляет Windows, а работаете вы на маке, и шрифты выдают этот стык двумя разными мерками. Первая это список имён: страница спрашивает по одному, какие шрифты у вас стоят. Вторая это родовое семейство: страница просит нарисовать cursive и меряет, чем нарисовано.

Команда ARMANOS7 мин

Страница спрашивает про шрифты дважды

Обе мерки страница снимает одним приёмом: рисует пробную строку и меряет её ширину. Разрешения она не спрашивает, и следа у вас не остаётся: ни запроса в сеть, ни окна с вопросом.

Первая мерка отвечает на простой вопрос: стоит ли у вас Menlo. Вторая на вопрос потруднее: чем ваша система закрывает слово cursive, когда шрифт по имени не назван.

  1. 1

    Рисует пробную строку

    Одну и ту же строку страница набирает разными шрифтами подряд.

  2. 2

    Меряет ширину

    У каждого шрифта ширина своя, и это готовое число.

  3. 3

    Сравнивает с запасным

    Совпало с запасным шрифтом значит такого шрифта у вас нет.

Список имён выдаёт чужую систему

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

Профиль Windows объявляет 14 шрифтов всегда, а ещё 18 стоят в запасе, откуда жребий берёт около половины; у профиля macOS 15 всегда и 20 в запасе. Поэтому длина списка у двух ваших профилей разная, и наборы расходятся сами.

Один чужой шрифт в этом списке ломает всё построение, сколько бы верных ни стояло рядом. Профиль, объявивший Windows и признающий при этом Menlo или Papyrus, описывает машину, какой никто не выпускал.

Какие шрифты стоят у профиля всегда

Ядро профиля Windows это четырнадцать имён, которые стоят на любой живой Windows: Arial, Courier New, Georgia, Segoe UI, Tahoma, Times New Roman, Trebuchet MS, Verdana и ещё шесть. Четыре из четырнадцати держат родовые семейства: Comic Sans MS, Impact, Cambria Math и Consolas.

Восемнадцать необязательных приходят жребием: Calibri, Cambria, Candara, Garamond, Century Gothic, Arial Black и другие, и порог у жребия 55 из 100. Поэтому у двух профилей Windows длина списка расходится сама, а два одинаковых списка встречаются реже, чем два одинаковых адреса.

Система профиляСтоят всегдаПриходят жребием
Windows1418
macOS1520
Linux2117

Второе имя того же шрифта

На маке у шрифта есть второе имя, короткое и служебное: Arial отзывается ещё и на ArialMT. Так устроен поиск шрифтов в macOS, и живой Mac отвечает на оба имени одинаково, одной и той же шириной.

На собранном движке Arial дал 898.76, а девять вторых имён по 850.62, то есть ровно ширину запасного шрифта.

Профиль, у которого Arial есть, а ArialMT нет, не похож ни на один настоящий Mac.

Поэтому у профиля macOS вторые имена заведены для 24 семейств, но в его список они попадают вместе с самим семейством: двенадцать из этих двадцати четырёх стоят в ядре и приходят с ним, остальные двенадцать приходят жребием. У профиля Windows вторых имён нет: Windows ищет шрифт по семейству и служебных имён не знает вовсе.

Родовое семейство это вторая мерка

Кроме имени, страница умеет попросить семейство: serif, sans-serif, monospace, cursive, fantasy или math. Живая машина отвечает на все шесть разными шрифтами, и ширины у них тоже разные, потому что за семейством стоит свой шрифт системы.

Замерено 18 августа: у профиля macOS на маке четыре семейства дали четыре разные ширины. У профиля Windows на том же маке все четыре сошлись в одну.

СемействоПрофиль macOS на макеПрофиль Windows на маке
serif840.66840.66
cursive842.34840.66
fantasy742.05840.66
math894.11840.66

Почему четыре ширины сходятся в одну

Слово cursive это не шрифт, а поручение: раскрыть его в настоящий шрифт обязана система, за которой вы сидите. На маке cursive раскрывается в Apple Chancery, fantasy в Papyrus, math в STIX Two Math.

Профиль Windows этих трёх шрифтов не объявляет, и запрет уводит их один за другим в запасной. Три семейства садятся на ширину serif, и одной мерки хватает, чтобы увидеть машину, какой не бывает.

Чем этот стык закрывается

Соответствие семейств браузер читает из настроек самого профиля, а каталог профиля ваш. Значит закрыть стык можно без пересборки: каждое семейство получает шрифт, который профиль и так объявляет.

После такой записи четыре ширины снова разошлись: семейства подставляются шрифтами ХОЗЯЙСКОЙ системы, и на маке это Apple Chancery, Papyrus и STIX Two Math, а Comic Sans MS с Impact стоят в строке для Windows.

Программа делает это только чужому шаблону: своя система раскрывает семейства правильно сама, и трогать её незачем.

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

Буквы рисуются, а список остаётся чистым

Чтобы буквы вообще нарисовались, браузеру нужны настоящие шрифты той машины, за которой вы сидите, а не имена из списка. Без них телефонный профиль на настольной машине выходит пустым листом: с одними андроидными именами ширина текста равна нулю сразу у всех семейств.

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

У телефона список короткий нарочно

У Android шрифтов правда мало, и это первое, чем телефон выдаёт себя. Настольного набора там нет вовсе: страница, которая мерит ширину Arial и получает ответ, уже знает, что перед ней не телефон.

Поэтому телефонный профиль объявляет короткий список: Roboto, Noto Sans, Noto Serif, Droid Sans Mono и несколько других. Родовые семейства у него свои: cursive раскрывается в Dancing Script, моноширинный в Droid Sans Mono, а математического шрифта на телефоне нет ни у кого, и math честно ложится на serif.

Как проверить свои профили за вечер

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

Потом проверьте второе имя: спросите про Arial и отдельно про ArialMT той же меркой. Настоящий Mac отвечает на оба одинаково, а профиль Windows не признаёт ни одного служебного имени.

  1. 1

    Померьте шесть семейств

    Одна строка, шесть ширин: совпавшие между собой ширины это и есть стык.

  2. 2

    Спросите второе имя

    У профиля macOS Arial и ArialMT обязаны отвечать одинаково.

  3. 3

    Сверьте список с системой

    Шрифта, которого на объявленной системе не бывает, в списке быть не должно.

  4. 4

    Повторите на соседнем профиле

    Два набора, совпавшие до буквы, площадка сводит в пару.

Чего это не утверждает

  • Это не утверждает, что четыре разные ширины делают профиль безопасным. Убран один стык из многих, а поведение, платёжные данные и история аккаунта остаются при вас.
  • Числа выше сняты 18 августа на одной машине и на одном поколении отпечатка. Другой набор шрифтов даёт другие ширины.
  • Семейства программа назначает только чужому шаблону и берёт их из зашитой таблицы по имени вашей системы, а не опросом диска. Проверка одна: шрифт обязан стоять в списке профиля. Если запись настроек не удалась, вы получите предупреждение. Если назначать оказалось нечего, семейства останутся прежними, и сообщения об этом не будет.
  • Это не утверждает, что такую мерку снимает каждый сайт. Кто-то меряет, кто-то не смотрит вовсе, и никто из них не публикует, что именно проверяет.

Где это можно увидеть самому

Каждое число выше выходит из кода, который можно открыть и запустить.

Список шрифтов профиля выводится из зерна: ядро плюс часть необязательных
packages/shared/src/index.js
Вторые имена добавляются только там, где система на них отвечает
packages/shared/src/index.js
Родовые семейства назначаются чужому шаблону и только объявленными шрифтами
apps/desktop/src/lib/genericFonts.js · apps/desktop/test/generic-fonts.js
Шесть семейств дают шесть разных шрифтов в живом браузере на каждом шаблоне
apps/desktop/test/engine-text-renders.js
Подкладка под рисование не попадает в ответ страницы
apps/desktop/test/дыры-движка-закрыты.js
Запрет чужого шрифта стоит в самом движке
engine/patches/armanos-fp.cumulative.diff

Вопросы

Можно просто подменить строку user agent?
Нет: список шрифтов и родовое семейство читаются отдельно от неё. Подменив одно поле, вы чаще заводите новое расхождение, чем закрываете старое.
Если объявить побольше шрифтов, будет лучше?
Нет. Щедрый список сам по себе выглядит странно, а одно имя с чужой системы выдаёт стык первой же меркой.
Почему не выдать всем профилям один набор?
Одинаковый до буквы набор связывает ваши аккаунты надёжнее любого адреса. Наборы обязаны расходиться от профиля к профилю.
Я на маке и профиль маковский, это всё лишнее?
Своя система раскрывает семейства правильно сама, и назначать там нечего. Ширины посмотреть всё равно стоит: список шрифтов у вас свой.
Помогает ли режим инкогнито или блокировщик?
Нет. Ширину строки ваша машина меряет у себя, без единого запроса наружу, и закрывать тут нечего.
Сколько времени уходит на один профиль?
Обе мерки вы снимете за пару минут в окне разработчика. Дольше идёт обход профилей парами, и десяток за вечер это спокойный ход.

Посмотрите, какие шрифты называет ваш браузер

Проверка читает 12 значений прямо в окне и никуда их не отправляет.