Поделиться через


Отображение текста с помощью Uniscribe

Приложения могут использовать функции API Юниписи для поддержки типографии и отображения и редактирования международного текста. Юниписец использует абзац в качестве единицы для отображения текста, а функции Юниписи должны использоваться для всего абзаца.

При использовании Юниписи для отображения текста приложение должно пройти процесс форматирования (макета), обычно используя Uniscribe. Приложение делит текстовый абзац на фрагменты символов с одинаковым стилем, называемые "фрагментами". Стиль определяется определенной реализацией, но обычно включает такие атрибуты, как шрифт, размер и цвет. При определении сегментов приложение также может использовать другие сведения, такие как язык и региональные данные, которые поддерживаются для использования с лексическими инструментами. Например, приложение может рассматривать отрывок, представленный на французском языке, как отдельный фрагмент в тексте, главным образом написанном на английском языке.

После определения запусков для всех абзацев приложение делит каждый абзац на строки с одинаковым скриптом и направлением ("элементы"). Приложение применяет сведения об элементе для создания направлений, которые отличаются уникальным шрифтом и направлением и полностью находятся в одном элементе ("диапазоны").

Разделение элемента на диапазоны в некоторой степени произвольно, тем не менее диапазон должен состоять из одной или нескольких последовательных групп неделимых символов, которые называются "кластерами". Для европейских языков кластер обычно соответствует одному символу кодовой страницы или точке кода Юникода и содержит один глиф . Однако на таких языках, как тайский, кластер представляет собой группирование глифов и соответствует нескольким последовательными символами или точками кода. Например, тайский кластер может содержать консонант, гласный и тоновый знак. Чтобы не разбивать кластеры, приложение обычно должно использовать максимально длинные диапазоны или применять собственные лексические данные для разбиения между диапазонами в местах, не расположенных в середине кластера.

Когда он определил кластеры в каждом диапазоне, приложение должно определить размер каждого кластера. Он использует Uniscribe для суммирования кластеров для определения размера каждого диапазона. Затем приложение суммирует размеры диапазонов, пока они не переполняют строку, то есть достигает поля. Диапазон, который переполнен линией, делится между текущей строкой и следующей строкой. Для каждой строки приложение создает карту из визуальной позиции в логическую позицию для каждого диапазона. Затем приложение формирует точки кода для каждого диапазона в глифы, которые впоследствии могут размещаться и отображаться.

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

Приложение, использующее сложные скрипты , имеет следующие проблемы с простым подходом к макетированию и отображению.

  • Ширина сложного символа скрипта зависит от его контекста. Невозможно сохранить ширину в простых таблицах.
  • Разрыв между словами в таких системах написания, как тайский, требует поддержки словаря. Например, между тайскими словами не используется символ разделителя.
  • Для арабского, иврита, персидского, урду и других языков с двунаправленным текстом требуется переупорядочение перед отображением.
  • Для простого использования сложных скриптов часто требуется некоторая форма сопоставления шрифтов.

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

Заметка

Юнипись должна использоваться для всего абзаца, даже если разделы абзаца не являются сложными скриптами.

 

Как показано в следующей таблице, Uniscribe версии 1.6 или более поздней поддерживает несколько функций, которые используют преимущества тегов OpenType. Их можно заменить соответствующими обычными функциями Юниписи. Как правило, приложения должны работать полностью с функциями из одного набора или другого и не должны пытаться смешивать и сопоставлять функции.

Обычная функция Юнискрайб Эквивалентная функция OpenType
ScriptItemize ScriptItemizeOpenType
ScriptShape ScriptShapeOpenType
ScriptPlace ScriptPlaceOpenType

 

Выложить текст с помощью Юниписи

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

  1. Вызов ScriptRecordDigitSubstitution выполняется только при запуске или при получении сообщения WM_SETTINGCHANGE.

  2. (Необязательно) Вызовите ScriptIsComplex, чтобы определить, требуется ли для абзаца сложная обработка.

  3. (Необязательно) При использовании Юниписи для обработки двунаправленного текста и (или) подстановки цифр вызовите ScriptApplyDigitSubstitution, чтобы подготовить структуры SCRIPT_CONTROL и SCRIPT_STATE в качестве входных данных для ScriptItemize. Если пропустить этот шаг, но при этом требуется подстановка цифр, замените национальные цифры на цифры в диапазоне Юникод U+0030 до U+0039 (европейские цифры). Для получения информации о замене цифр см. в разделе Формы цифр.

  4. Вызовите ScriptItemize, чтобы разделить абзац на элементы. Если не использовать Юнипись для подстановки цифр и двунаправленный порядок известен, например, из-за раскладки клавиатуры, используемой для ввода символа, вызовите ScriptItemize. В вызове укажите указатели null для структур SCRIPT_CONTROL и SCRIPT_STATE. Этот метод создает элементы только с помощью процессора формирования, а затем их можно переупорядочить с использованием информации о подсистеме.

    Заметка

    Как правило, приложения, работающие только с скриптами слева направо и без подстановки цифр, должны передавать указатели NULL для структур SCRIPT_CONTROL и SCRIPT_STATE.

     

  5. Объедините сведения об элементе с информацией о запуске для создания диапазонов.

  6. Вызовите ScriptShape для идентификации кластеров и создания глифов.

  7. Если ScriptShape возвращает код USP_E_SCRIPT_NOT_IN_FONT или S_OK с выходными данными, содержащими отсутствующие глифы, выберите символы из другого шрифта. Либо замените шрифт, либо отключите формирование, установив элемент eScript структуры SCRIPT_ANALYSIS, передаваемый в ScriptShape, на значение SCRIPT_UNDEFINED. Для получения дополнительной информации см. раздел Использование резервных шрифтов.

  8. Вызовите ScriptPlace для создания расстояний и позиций по x и y для глифов в каждом последующем диапазоне. Это первый шаг, для которого размер текста становится вопросом.

  9. Суммируйте размеры диапазона, пока строка не переполнится.

  10. Разорвать диапазон по границе слова с помощью членов fSoftBreak и fWhiteSpace в логических атрибутах. Чтобы отделить символьный кластер из последовательности, используйте сведения, возвращаемые вызовом ScriptBreak.

    Заметка

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

     

  11. Повторите шаги 6–10 для каждой строки абзаца. Однако при нарушении последнего запуска в строке вызовите ScriptShape, чтобы изменить оставшуюся часть выполнения в качестве первого запуска в следующей строке.

Отображение текста с помощью Uniscribe

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

Заметка

Приложение может опустить шаг 2, если текст не содержит символов из скриптов справа налево, не содержит двунаправленных символов управления и использует уровень внедрения слева направо.

 

  1. Для каждого запуска выполните следующие действия:

    1. Если стиль изменился с момента последнего запуска, обновите дескриптор до контекста устройства, отпустив и снова получив его.
    2. Вызовите ScriptShape для создания глифов для выполнения.
    3. Вызовите ScriptPlace, чтобы создать опережающую ширину и смещение по осям x и y для каждого глифа.
  2. Выполните следующие действия, чтобы установить правильный визуальный порядок для выполнения в строке:

    1. Извлеките массив двунаправленных уровней внедрения, по одному на диапазон. Уровень вложенности определяется (SCRIPT_ITEM) si. (SCRIPT_ANALYSIS) a. (SCRIPT_STATE) s.uBidiLevel.
    2. Передайте этот массив в ScriptLayout, чтобы создать карту отображения визуальных позиций на логические позиции.
  3. (Необязательно) Чтобы оправдать текст, вызовите ScriptJustify или используйте специализированные знания о тексте.

  4. Используйте визуально-логическую карту для отображения запусков в визуальном порядке. Начиная с левого конца строки вызовите ScriptTextOut, чтобы отобразить выполнение, заданное первой записью на карте. Для каждой последующей записи в карте вызовите ScriptTextOut, чтобы отобразить указанный запуск справа от ранее отображаемого запуска.

    Если опущен шаг 2, начните в левом конце строки и вызовите ScriptTextOut, чтобы отобразить первый логический запуск, а затем отобразить каждый логический запуск справа от предыдущего запуска.

  5. Повторите описанные выше действия для всех строк в абзаце.

Использование Uniscribe