Красивые шрифты: как устроен Unicode и где он ломается
Почему красивый текст — это символы, а не шрифты, какие площадки его принимают, что он делает с лимитом символов и экранным диктором, и какие 24 буквы Unicode не закодировал.
Вставьте 𝐛𝐨𝐥𝐝 в описание профиля в Instagram — останется жирным. Вставьте туда же жирный текст, скопированный из Word, — получите обычный. На этом спотыкаются постоянно и решают, что одно из двух сломано. Не сломано ни то, ни другое. Просто одно из них вообще не форматирование.
Это символы, а не шрифты
Шрифт — это набор рисунков для символов, которые у вас уже есть. Жирное начертание в Word означает «нарисуй эту A потолще», но сама A под ним по-прежнему U+0041. Указание про толщину живёт в документе, а не в букве, поэтому стоит убрать форматирование документа — и возвращается обычная A.
𝐀 устроена иначе. Это U+1D400, MATHEMATICAL BOLD CAPITAL A, отдельный символ, закодированный ещё в Unicode 3.1 в 2001 году. Жирность вшита в саму личность символа. Поле профиля может вырезать любое форматирование, какое найдёт, а 𝐀 переживёт это, потому что вырезать нечего.
Unicode придумал такое не ради Instagram. Математикам нужно отличать 𝐴-скаляр от 𝐀-вектора и от 𝔸-поля: это три разных объекта, а не один объект в трёх начертаниях. Через канал с обычным текстом типографское указание такой смысл не протащить, поэтому различие пришлось загнать в сами символы. Генератор красивых шрифтов — это побочное применение системы обозначений, придуманной для алгебры.
Двадцать четыре буквы, на которых спотыкается большинство генераторов
Быстрый способ отличить аккуратный генератор от ленивого: наберите «hi» и посмотрите на курсив.
Ленивый прибавляет к каждой букве постоянное смещение. Курсивная строчная a стоит на U+1D44E, значит курсивная h должна быть седьмой дальше, на U+1D455. Вот только U+1D455 навсегда не занята — и вы получаете квадратик.
Причина историческая. Когда математический блок только проектировали, часть этих букв уже была закодирована по отдельности как именованные константы, а дважды один и тот же символ Unicode не кодирует. Постоянная Планка ℎ попала на U+210E. Прописная ℬ Бернулли — на U+212C. Готическая ℜ, которой математики обозначают вещественную часть, — на U+211C. Всего осталось двадцать четыре дырки с пометкой «смотри в другом месте»:
- Курсив: h
- Пропись: B, E, F, H, I, L, M, R, e, g, o
- Готика: C, H, I, R, Z
- Контурный: C, H, N, P, Q, R, Z
Наберите «Hello» прописью в нескольких генераторах и посмотрите, что вернётся. Те, где выходит ℋℯ𝓁𝓁ℴ, таблицу исключений знают. Те, где выходит квадратик и три буквы за ним, — нет.
Какие поля это принимают
Правило устроено куда последовательнее, чем кажется по форумам. Стилизованные символы разрешены там, где поле читает человек, и запрещены там, где его разбирает машина.
Discord пустит красивый текст в отображаемое имя и в ник на сервере и не пустит в имя аккаунта. Instagram пустит в поле имени и в описание, но никогда — в @адрес. Telegram, X и YouTube проводят ту же черту. Идентификатор проверяют по списку допустимых символов; отображаемое имя — украшение, оно проходит насквозь.
Если форма профиля молча отказывается сохраняться и не показывает никакой ошибки, стилизованные символы — первое, что стоит исключить.
Чем за это платят
Двумя вещами, и ни одной не видно в результате.
Экранные дикторы справляются плохо. VoiceOver и NVDA читают 𝐇𝐞𝐥𝐥𝐨 как набор математических знаков, проговаривают по букве или пропускают. Это не ошибка программы: кодовые позиции действительно означают «математическая жирная заглавная H», и диктор точен относительно того, что вы написали. Поисковики рассуждают так же, поэтому стилизованное ключевое слово в заголовке ролика — выброшенное ключевое слово. Одна декоративная строка — нормально. Абзац — нет.
Вторая плата — лимит символов. Большинство стилизованных букв лежит выше U+FFFF, то есть занимает две единицы UTF-16 вместо одной. Instagram считает кодовые позиции и видит в 𝐀 один символ, а многие проверки форм считают единицы UTF-16 и уверяют, что описание из 90 символов весит 180. С украшениями ещё хуже: зачёркивание приваривает лишний символ к каждой букве, так что зачеркнуть строку из 30 символов стоит 60. Рядом с каждым стилем генератор печатает число кодовых позиций — это и есть цифра, на которую стоит смотреть до вставки.
Кириллица, греческий и всё остальное
Жирной кириллицы в Unicode нет. Нет и арабского в кружках, нет прописного иврита. Математический блок покрывает латиницу и кусок греческого — на этом опись заканчивается, у большинства письменностей мира стилизованного двойника нет вовсе, и выдумать его не может ни один генератор.
Две вещи работают на любой письменности, потому что это знаки поверх букв, а не замена букв: диакритические украшения (зачёркивание, подчёркивание, надчёркивание) и обрамления. п̶р̶и̶в̶е̶т̶ получается прекрасно. 𝐩𝐫𝐢𝐯𝐞𝐭 требует сначала транслитерации, а это обычно не то, чего хотели.
Выберите стиль, посмотрите на счётчик и вставляйте: Генератор красивых шрифтов работает целиком в браузере, двадцать три стиля, у каждого своя кнопка копирования.