Почему «ё» выглядит по-разному после копирования: Unicode и шрифт

«Ё» и «ё» могут быть записаны в тексте как один Unicode-символ или как буква Е/е вместе с комбинируемым знаком диерезиса. Эти последовательности канонически эквивалентны, но проверяются в шрифте по-разному. Если после копирования точки съезжают, пропадают или меняют вид, проверьте состав строки, наличие знаков в шрифте и позиционирование комбинируемой диакритики.
Откуда берутся две записи одной «ё»
В обычном тексте заглавная «Ё» — это U+0401, строчная «ё» — U+0451. Но Unicode задаёт для них каноническое разложение: U+0401 соответствует последовательности U+0415 «Е» + U+0308 COMBINING DIAERESIS, а U+0451 — U+0435 «е» + U+0308. Поэтому человек видит одну букву с двумя точками, а программа может получить один или два кодовых пункта.
Это не две разные буквы и не ошибка кодировки. Это две канонически эквивалентные записи одной и той же абстрактной буквы. Нормализация NFC обычно собирает последовательность в составной символ, когда он предусмотрен; NFD, наоборот, раскладывает составной знак. Unicode описывает эти формы и требует, чтобы канонически эквивалентные строки после нормализации имели одинаковое представление для сравнения. Подробности есть в UAX #15 о нормализации Unicode, а коды букв можно сверить в официальной таблице кириллицы.
Практическая причина расхождения проста: приложение, сайт, редактор или база данных могли сохранить строку в разных нормализованных формах. Копирование само по себе не обязано превращать «ё» в разложенную запись, а каждая программа не обязана автоматически приводить текст к NFC. Поэтому сравнивать нужно именно получившиеся кодовые пункты, а не внешний вид на экране.
Кодовая точка — не готовая картинка
Шрифт связывает кодовые пункты с глифами, а механизм формирования строки решает, какие глифы показать и где их разместить. У буквы U+0451 может быть самостоятельный глиф «ё». В разложенной последовательности сначала идёт глиф «е», затем U+0308 — комбинируемая диакритика. Для аккуратной посадки знак должен располагаться относительно основы, а не как случайная вторая буква с собственным интервалом.
В OpenType для этого предусмотрено позиционирование mark-to-base: шрифт задаёт точки привязки для базовых глифов и диакритических знаков, чтобы знак выравнивался по опорным точкам буквы. Спецификация таблицы GPOS описывает такой механизм как способ позиционировать комбинируемые знаки относительно базового глифа. Поддержка зависит от шрифта и текстового движка, поэтому одной красивой составной «ё» недостаточно для проверки разложенного варианта.
Это различие особенно заметно в авторском шрифте. Если в нём есть U+0451, но нет U+0308, составной вариант может выглядеть правильно, а последовательность «е + ◌̈» — показать пустой прямоугольник, чужой знак из резервного шрифта или точки на неверной высоте. Если есть знак диерезиса, но нет корректной привязки к основе, он может оказаться слишком далеко, пересечься с верхом буквы или сместиться в сторону. Конкретный результат зависит от программы, операционной системы и правил подстановки шрифта.
Какие знаки проверить в собственном шрифте
Для кириллической «ё» недостаточно проверить, что в таблице символов видны две точки. Проверьте два регистра и оба способа представления:
- U+0401 «Ё» и U+0451 «ё» как самостоятельные составные символы;
- U+0415 «Е» и U+0435 «е» как базовые кириллические буквы;
- U+0308 COMBINING DIAERESIS как комбинируемый знак;
- позиционирование диерезиса над заглавной и строчной основой.
Рисунок U+0401/U+0451 может быть спроектирован как полноценная буква: точки могут иметь собственный размер, расстояние и оптическое положение. Для комбинируемого U+0308 важно, чтобы пара «основа + знак» оставалась узнаваемой и в разложенной последовательности. Внешнее сходство не требует механически одинаковых координат: ширина и форма заглавной Е отличаются от строчной е, поэтому отметка может нуждаться в разных точках привязки.
Визуальную логику пары стоит согласовать. Точки над заглавной «Ё» не должны случайно сливаться с соседней строкой или обрезаться рамкой строки; точки над строчной «ё» не должны превращать букву в неясную комбинацию. При этом не исправляйте проблему простым увеличением межстрочного интервала, пока не выяснили, что именно смещено: глиф, точка привязки, метрика строки или резервный шрифт.
Если шрифт предназначен только для коротких заголовков, это не отменяет проверку составных и разложенных форм. Название, фамилия или цитата могут прийти из разных источников. Проверка особенно нужна, если текст проходит через веб-форму, CMS, PDF, импорт из таблицы или поиск по базе: в разных местах строки могут сравниваться и преобразовываться по-разному.
Как проверить обе формы без специального ПО
Сначала создайте контрольный фрагмент, в котором видимые буквы похожи, но кодовые точки различаются. Сравните написанное «Ё ё» с последовательностями «Е◌̈ е◌̈». В последнем случае знак U+0308 нужно вводить как комбинируемую диакритику, а не как обычные кавычки или отдельную латинскую букву с умлаутом. В некоторых редакторах удобнее вставить заранее подготовленную строку.
Проверьте состав строки в любом редакторе, который показывает коды Unicode, или небольшим скриптом. Например, в браузерной консоли для заранее скопированного фрагмента можно получить кодовые точки выражением Array.from(text, ch => 'U+' + ch.codePointAt(0).toString(16).toUpperCase()). Для одной записи результат будет U+0451, для разложенной — U+0435 и U+0308. Не путайте кодовые точки с байтами UTF-8: одна кодовая точка может занимать несколько байтов, но от этого сама буква не становится другой.
Затем проведите четыре проверки:
- Наберите составные Ё и ё непосредственно в тестовой программе и убедитесь, что шрифт выбран именно ваш.
- Вставьте разложенные Е + ◌̈ и е + ◌̈ из другого источника. Проверьте форму, высоту, центрирование и отсутствие «чужих» точек.
- Скопируйте обе строки в веб-форму, редактор макета и документ, которые действительно нужны проекту. После вставки проверьте и картинку, и коды.
- Сохраните и снова откройте тестовый файл; если макет будет экспортироваться в PDF или изображение, проверьте также итоговый экспорт.
Если обе формы выглядят одинаково в одном приложении, тест ещё не доказывает совместимость везде. Он лишь подтверждает работу цепочки «данные → выбранный шрифт → текстовый движок» в этом конкретном месте. Проверяйте конечный сценарий, особенно если над файлом работают разные люди и устройства.
Как устранить расхождение
Если проект контролирует текстовую обработку, договоритесь об одной нормализованной форме на границе импорта и используйте её последовательно для поиска и сравнения. Для обычного текста Unicode FAQ рекомендует NFC как общий вариант; нормализация помогает привести канонически эквивалентные строки к общему представлению. Не применяйте NFKC автоматически к пользовательскому тексту: это более широкое преобразование и оно может убирать различия, которые для задачи важны. Сначала сохраняйте оригинал или обеспечьте резервную копию, затем тестируйте преобразование на реальных данных.
Нормализация текста не заменяет поддержку шрифта. Если проект должен отображать оба варианта входной строки, убедитесь, что в файле доступны составные Ё/ё и нужная комбинируемая диакритика, а в таблицах позиционирования заданы подходящие привязки. Проверьте, что система формирования текста не заменяет диерезис шрифтом-запасным только потому, что основной шрифт не содержит комбинируемый знак.
Если проблема только в высоте или горизонтальном положении точек, исправляйте геометрию глифов и привязки, затем повторяйте тест на заглавной и строчной основе. Если символ вообще отсутствует, проверьте карту Unicode и покрытие шрифта. Если кодовые последовательности отличаются после вставки, настройте обработку данных в конкретной программе или сервисе. Диагностируйте уровень, где возникает расхождение: иначе легко испортить рисунок букв, пытаясь исправить нормализацию, или изменить текст там, где требовалась правка GPOS.
Чек-лист перед передачей шрифта
- Проверьте в карте символов U+0401, U+0451 и U+0308.
- Сравните составные и разложенные варианты в верхнем и нижнем регистре.
- Убедитесь, что точки диерезиса относятся к кириллической Е/е, а не подменяются похожими глифами.
- Посмотрите, не появляются ли пустой квадрат, чрезмерный зазор, наклон или обрезание знака.
- Проверьте шрифт в приложениях, где текст будут вводить, редактировать, искать и экспортировать.
- Зафиксируйте, какая нормализация применяется к тексту, если проект преобразует строки.
- Повторите проверку после изменения глифов, таблиц позиционирования или экспорта файла.
Частые ошибки
**Проверить только набранную «ё».** Это покрывает U+0451, но не гарантирует работу комбинации е + U+0308. Добавьте разложенный вариант в тестовую строку.
**Считать одинаковый вид доказательством одинаковой строки.** Кодовые точки могут различаться при полностью одинаковом отображении. Если важны поиск и сопоставление, проверяйте представление данных отдельно.
**Считать любые две точки диерезисом.** В строке может стоять отдельный символ, другой комбинируемый знак или знак из резервного шрифта. Сверьте точку U+0308.
**Исправлять всё через NFKC.** Эта форма предназначена для преобразования совместимых вариантов, а не для универсальной починки отображения. Для общего текста рассмотрите NFC и оцените последствия на копии.
**Подправлять только высоту строки.** Если точки принадлежат резервному шрифту или не привязаны к букве, увеличение интерлиньяжа не исправит положение пары. Сначала определите причину.
Частые вопросы
«Ё» и «е + ◌̈» — это разные буквы?
Для Unicode это канонически эквивалентные записи одной буквы: составной символ имеет каноническое разложение на базовую кириллическую Е/е и комбинируемый диерезис. В строке они могут быть разными последовательностями кодовых точек, поэтому поиск или двоичное сравнение без нормализации может дать разные результаты.
Почему в шрифте есть «ё», но комбинация точек не работает?
Составная буква U+0451 может иметь отдельный глиф, а разложенная запись требует также U+0308 и корректной обработки диакритики. Проверьте наличие комбинируемого знака, покрытие кириллической основы и позиционирование в используемом текстовом движке.
Нужно ли вручную добавлять U+0308 в авторский шрифт?
Если шрифт должен принимать произвольный Unicode-текст и отображать разложенные формы, добавьте этот знак и проверьте его привязку к базовым глифам. Для строго контролируемого набора составных букв это может быть отдельным решением проекта, но проверьте входные данные и приложения до передачи файла.
Всегда ли копирование превращает «ё» в две кодовые точки?
Нет. Копирование не обязано менять нормализованную форму. Разные последовательности могут появиться из-за источника текста, редактора или обработки строки; сравните коды до и после вставки, чтобы установить, произошло ли преобразование.
Какую форму нормализации выбрать?
Для общего текста Unicode FAQ называет NFC подходящим общим выбором, но система может иметь требования к сохранению исходного представления. Зафиксируйте правило на границе импорта и согласуйте его с поиском, хранением и экспортом. Не меняйте данные массово без проверки на копии.
Можно ли проверить это только на картинке?
Нет. Изображение показывает результат формирования строки, но не её кодовые точки. Используйте два этапа: посмотрите, как пара отображается в нужном приложении, затем определите кодовые точки, чтобы понять, составная перед вами запись или разложенная.
Вывод
Надёжная проверка «ё» охватывает не только U+0401 и U+0451, но и разложенную пару Е/е + U+0308. Сначала узнайте, какие кодовые точки приходят из источника, затем проверьте покрытие шрифта и позиционирование в конечных программах. Если вы собираете собственный шрифт, проверьте его на коротком фрагменте с обеими формами, а для быстрой пробы можно создать основу в Fontgenerator.