Все статьи
24 сентября 2026 г.9 мин чтения

Как проверить кириллический шрифт на комбинируемые знаки и NFC/NFD

Как проверить кириллический шрифт на комбинируемые знаки и NFC/NFD

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

Почему одна буква бывает записана двумя способами

В Unicode текст хранится как последовательность кодовых точек. Некоторые знаки существуют как отдельный символ, другие могут быть представлены сочетанием базовой буквы и комбинируемого знака. Unicode называет такие последовательности канонически эквивалентными, если они обозначают один и тот же абстрактный текст. Визуально они должны вести себя согласованно, но на уровне кода это не обязательно один и тот же набор чисел.

Например, заглавная Й может быть записана одной кодовой точкой U+0419 либо как И U+0418 и комбинируемая кратка U+0306. Аналогично Ё U+0401 имеет каноническое разложение Е U+0415 и комбинируемая диерезис U+0308. А в словарной записи ударение часто вводят отдельной последовательностью: гласная плюс комбинируемое острое ударение U+0301. Это не означает, что все кириллические буквы с надстрочными элементами имеют такие же разложения: проверяйте конкретный знак и его данные Unicode.

Формы NFC и NFD — два способа привести канонически эквивалентный текст к упорядоченному виду. NFD раскладывает некоторые составные символы на основу и знак; NFC сначала выполняет такое разложение, а затем снова объединяет те пары, для которых предусмотрена композиция. Ни одна из форм не заменяет работу над глифами: приложение может сохранить исходную последовательность, а шрифт должен уметь показать поступившие символы и корректно их расположить. Описание алгоритма есть в Unicode Standard Annex #15.

Какие части шрифта участвуют в показе

Для отдельного символа важна карта cmap: она связывает кодовую точку с глифом. Если в шрифте есть Й, но отсутствует U+0306, строка из И плюс кратки может показать пустой прямоугольник, пропустить знак или подставить его из другого шрифта. Для комбинируемого знака недостаточно только нарисовать контур: ему нужно назначить корректную категорию и подготовить позиционирование относительно базовой буквы.

В OpenType позицию метки обычно задают через GPOS, в частности через привязку mark-to-base: у знака и базового глифа есть соответствующие опорные точки. Для нескольких меток может понадобиться и привязка mark-to-mark. Спецификация OpenType GPOS описывает эти механизмы. Таблица cmap задаёт соответствие кодов глифам. Конкретный результат зависит также от движка формирования строк, браузера, редактора и режима набора, поэтому проверять нужно именно целевые приложения, а не только список глифов в редакторе шрифта.

Различайте отсутствие глифа и неправильную позицию. Если острая метка видна отдельно на базовой линии или слишком далеко от гласной, кодовая точка, вероятно, попала в шрифт, но настройка позиционирования или класс знака требует внимания. Если пропадает целая часть последовательности, сначала проверьте карту кодовых точек, выбранный файл шрифта и подстановку. Проверить назначение cmap можно через FontForge или утилиту просмотра таблиц; спецификация OpenType также определяет назначение этой таблицы.

Соберите минимальный тестовый набор

Не начинайте с огромного списка Unicode. Добавьте в контрольную строку только те знаки, которые реально нужны вашему проекту, и для каждого различайте кодовую точку и видимую форму. Для универсального кириллического шрифта полезно отдельно проверить готовые Й и Ё, их разложенные варианты, а также несколько последовательностей с комбинируемым ударением. В двуязычном словаре добавьте реальные слова из редакционного набора: изолированная буква не покажет, как надстрочный знак ведёт себя рядом с высокими строчными или прописными.

  • Й / И + U+0306: проверить готовую и разложенную запись одной буквы.
  • Ё / Е + U+0308: сравнить высоту, расстояние и ширину строки.
  • и + U+0301 и И + U+0301: проверить комбинируемое ударение в нижнем и верхнем регистре.
  • а + U+0300 или у + U+0300: добавить только если такие формы есть в реальных текстах.
  • гласная + два знака: использовать лишь для поддерживаемого языка и проверить порядок их наложения.

Запишите рядом кодовые точки, например U+0438 U+0301, а не только похожее на экране слово. Это даст коллеге воспроизводимый тест и позволит отличить комбинируемое U+0301 от самостоятельного знака ударения или визуально похожего символа. Названия и свойства кодовых точек сверяйте с официальными таблицами Unicode, например с блоком Combining Diacritical Marks.

Сравните NFC и NFD без догадок

Создайте две версии одной и той же строки из настоящего текста: первую сохраните в NFC, вторую преобразуйте в NFD. Это можно сделать в редакторе, который явно показывает форму нормализации, или небольшой программой. Для воспроизводимой проверки подойдут Python и встроенный модуль unicodedata: `unicodedata.normalize("NFC", text)` и `unicodedata.normalize("NFD", text)`. Не применяйте NFKC или NFKD вместо NFC/NFD без отдельной причины: compatibility-нормализация может менять другие различия символов, которые для верстки и содержания значимы.

Сначала сравните строку в обычном текстовом редакторе, который способен показывать кодовые точки, а затем откройте обе версии рядом в приложении, где будет использоваться шрифт. Не судите только по копированию текста из браузера: при вставке промежуточная программа может нормализовать строку. Если нужен точный контроль, сохраните тест в UTF-8 и отдельно проверьте последовательность кодовых точек скриптом либо инспектором символов.

  1. Сохраните исходные слова и выпишите их коды до преобразования.
  2. Получите NFC и NFD из одной исходной строки, не набирайте варианты вручную.
  3. Откройте оба файла в одном приложении с тем же файлом шрифта и масштабом.
  4. Сравните не только форму знака, но и межстрочное расстояние, переносы и ширину строки.
  5. Повторите пробу в браузере или редакторе, который является целевой средой проекта.

Канонически эквивалентные версии не обязаны иметь побайтно одинаковые данные. Задача теста — увидеть согласованное отображение и понять, где именно появляется расхождение. Если после нормализации одна версия стала составной буквой, а другая осталась базовой буквой с меткой, это ожидаемо для некоторых знаков; критично, чтобы обе строки корректно обрабатывались в поддерживаемом сценарии.

Настройте и оцените положение меток

Рисуйте комбинируемый знак как самостоятельный глиф, пригодный к переиспользованию, а не как часть одного-единственного слова. Для метки задайте опорную точку, для базовых кириллических букв — соответствующие точки привязки. Проверьте широкие и узкие буквы, прописные и строчные: одна универсальная координата может хорошо сесть над И, но оказаться слишком далеко от узкой и или столкнуться с соседним элементом в широком слове. Если два знака ставятся один над другим, оцените их порядок и запас пространства до строки выше.

Сравнивайте относительную позицию, а не только абсолютную высоту в файле шрифта. У гласных различаются ширина, наклон и верхний контур; метке нужен стабильный визуальный отступ. Для рукописного или наклонного начертания опорная точка может смещаться относительно вертикальной оси, но не должна нарушать узнаваемость буквы. Не выравнивайте все метки механически по одному x-координатному значению, если форма базовых глифов заметно отличается.

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

Используйте слова, которые выявляют проблемы

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

Печатная проба полезна даже для экранного набора, если надстрочные знаки занимают много места: она быстро выявляет столкновение со строкой выше. Для веба проверьте и файл WOFF2, и исходный OTF/TTF. При субсеттинге убедитесь, что в итоговый файл вошли как кодовые точки комбинируемых знаков, так и необходимые глифы и таблицы позиционирования. Проверка исходного файла не гарантирует, что оптимизатор сохранил нужные данные.

Частые ошибки при работе с комбинируемыми знаками

  • Проверять только Й и Ё и считать, что любая строка NFD автоматически заработает: у отдельных меток могут отсутствовать глифы или позиционирование.
  • Сравнивать вручную набранные слова: клавиатура или приложение могли создать разные последовательности и скрыть причину расхождения.
  • Считать любой видимый акцент отдельной буквой либо, наоборот, комбинируемым знаком: сначала запишите кодовую точку.
  • Добавлять знак в cmap, но не тестировать положение над разными базовыми глифами.
  • Проверять только в редакторе шрифта и не открывать реальную веб-страницу, документ или печатный макет.
  • Применять compatibility-нормализацию без необходимости и менять символы за пределами задачи.

Если результат отличается, локализуйте слой проблемы в таком порядке: исходная строка и кодовые точки; форма нормализации; наличие символов в файле; подстановка шрифта; позиционирование в GPOS; версия и поведение приложения. Такая последовательность помогает не перерисовывать знак, когда причина, например, в резервном шрифте или субсете.

Контрольный список перед выпуском

  • Зафиксируйте нужные кодовые точки и реальные текстовые примеры.
  • Сгенерируйте NFC и NFD из одного источника и подпишите версии.
  • Проверьте наличие комбинируемых знаков в cmap и связанное позиционирование.
  • Сравните прописные, строчные, узкие, широкие и наклонные базовые буквы.
  • Проверьте файл после экспорта в браузере, редакторе и, при необходимости, на печати.
  • Сохраните снимок, сведения о версии шрифта и обнаруженные расхождения.

Для собственного проекта можно собрать кириллический набор в Fontgenerator, затем использовать полученный файл как основу теста: отдельно откройте текст с готовыми буквами и с комбинируемыми знаками. Это не заменяет проверку таблиц и рендеринга, зато помогает увидеть реальные контуры в выбранном начертании.

Вопросы и ответы

Нужно ли нормализовать весь текст перед показом?

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

Если Й отображается, значит ли это, что И плюс кратка тоже работает?

Нет. Готовая Й и последовательность И с U+0306 могут проходить разные пути формирования глифов. Проверьте отдельно символ U+0419 и пару U+0418 U+0306; убедитесь, что оба сценария дают ожидаемую форму и положение.

Нужно ли включать все комбинируемые знаки Unicode?

Нет. Состав набора определяют языки, тексты и задачи продукта. Добавьте только знаки, которые действительно нужны; для каждого зафиксируйте кодовую точку и контрольные слова. Большой неподтверждённый набор увеличивает работу по рисунку и тестированию, но не гарантирует поддержку нужного языка.

Почему комбинируемое ударение оказывается на соседней букве?

Причиной может быть отсутствие правильной привязки метки к базе, некорректная связь в движке набора или изменённая последовательность символов. Сверьте коды строки, наличие глифа U+0301, таблицу GPOS и результат в другом целевом приложении. Если ошибка проявляется только в одном месте, сравните его шрифтовую подстановку и настройки рендеринга.

Можно ли проверить это только в FontForge?

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

Чем NFC отличается от NFKC?

NFC приводит текст к канонической композиционной форме. NFKC дополнительно использует совместимостные преобразования и может сводить некоторые различающиеся по назначению формы к общему представлению. Для проверки шрифтовой поддержки используйте NFC и NFD, если задача касается канонически эквивалентных строк; выбирайте NFKC только когда это обосновано правилами обработки самого текста.

Итог

Тест комбинируемых знаков состоит из трёх проверок: одинаково ли интерпретируются коды, есть ли все нужные глифы и правильно ли метки привязаны к кириллической основе. Сохраните пару NFC/NFD, реальный набор слов и список приложений, где проба прошла. Так вы превратите проверку диакритики из разового визуального взгляда в повторяемый контроль шрифта.