OberonCore
https://forum.oberoncore.ru/

Кернинговые пары и вывод текста
https://forum.oberoncore.ru/viewtopic.php?f=24&t=2479
Страница 1 из 1

Автор:  Димыч [ Среда, 24 Март, 2010 20:23 ]
Заголовок сообщения:  Кернинговые пары и вывод текста

Info21 писал(а):
Но нетривиально то, что тут нужен выход на таблицы kerning pairs в шрифтах.

Ничего сложного в парах кернинга нет.

Немного теории (для понимания)
Кернинг — подрезка литер при т.н. высокой печати, когда слова составлялись из отдельных букв и была необходимость изменять «полуапроши» для удобства чтения и равномерного набора. Понятие «кернинговая пара» происходит от того, что значение кернинга (как правило, отрицательное), задается для пары символов (или глифов), например A-V, A-W, L-v и т.д. Кернинг задается для разных кеглей (размер шрифта измеряется в пунктах и называется кегль шрифта) отдельно.
Рядом с кернингом стоит упомянуть о существовании лигатур.

При цифровом наборе понятие осталось.
Далее речь пойдет только о Windows.

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

Для простого графического вывода информация о кернинге не используется . Например, TextOut и ExtTextOut (последняя применяется в ББ) в большинстве случаев информацию о кернинге не используют. Берется только ширина каждого символа и на основе этой ширины строится строка, выводимая на контекст устройства.

Вывод текста в ББ
Примерно так и организован вывод текста в ББ. Создается таблица шрифтов (кэш шрифтов), для каждого шрифта в кэше создается массив, в который записывается ширина каждого используемого символа и затем эта информация используется для подготовки текста к выводу. Подробности в HostPorts.DrawString и HostPorts.DrawSString.
Я понимаю, почему Оминк приняли такое решение. ББ разрабатывался для использования в Windows 3.1, затем в 95/98. Вариантов вывода текста было, по сути, только два — простой или по отдельным символам (глифам). Второй хоть и визуально дает более привлекательный результат, но гораздо более трудоемок.

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

В Windows 2000 появилась функция, которая сразу организует «правильный» вывод текста. Точнее не вывод, а подготовку к выводу. Функция эта — GetCharacterPlacement. Она получает на вход указатель на структуру данных, в которой есть указатели на несколько массивов. В этих массивах после вызова функции содержится следующая информация:
  • выводимая строка в измененном виде (см. ниже);
  • порядок следования глифов;
  • начальные координаты каждого глифа;
  • координаты каретки возле каждого глифа;
  • список глифов.
После вызова функции указанная структура содержит информацию о порядке следования глифов, которые соответствуют символам входной строки. Глифы располагаются с учетом замены символов лигатурами, с учетом метрик шрифта и с учетом информации о кернинге. Кроме того, учитывается еще и хинтовка шрифтов (т.е. используются квадратичные или кубические сплайны). Все это регулируется флагами на входе в функцию GetCharacterPlacement.

Сам вывод осуществляется функцией ExtTextOut с использованием параметра ETO_GLYPH_INDEX.

Функция GetCharacterPlacement может работать с разными языками, в том числе и с RTL-написанием, и с арабской вязью, где несколько символов могут быть заменены одним/несколькими глифами. Именно для этой цели в структуре, упомянутой выше содержится выводимая строка. Она, после вызова, может отличаться от входной довольно значительно.

Что очень важно, функция работает быстро.

Изменения в ББ
Чтобы использовать описанный механизм в ББ придется пересмотреть весь вывод текста. При определении позиции вставки в ББ широко используется функция GetCharWidth32W, определяющую ширину символа вместе с метриками. Придется пересмотреть этот механизм и определять ширину символов и потенциальную позицию каретки с помощью предварительно кэшированной информации, возвращенной фукнцией GetCharacterPlacement. Кроме того, придется рассмотреть вопрос о стыковке view и текста, стыковке текста разного начертания и др.
Но, в очередной раз следует отдать должное Оминк, все очень неплохо локализовано и изменения будут в считанных местах. HostPorts я уже назвал.
Да, важное замечание: GetCharacterPlacement ожидает на вход строку в UNICODE, не в UTF-8!

PS. Если интересно, могу выложить проект (на Delphi), в котором я экспериментировал с функциями GetCharacterPlacement и ExtTextOut. Предваряя вопрос, почему не ББ, скажу, что в Delphi заведомо работающие прототипы функций, мне не хотелось еще и их (прототипы) отлаживать.

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

Автор:  Евгений Темиргалеев [ Среда, 24 Март, 2010 20:28 ]
Заголовок сообщения:  Re: Кернинговые пары и вывод текста

Димыч писал(а):
Да, важное замечание: GetCharacterPlacement ожидает на вход строку в UNICODE, не в UTF-8!
UNICODE = UCS2?

Автор:  Александр Ильин [ Среда, 24 Март, 2010 21:29 ]
Заголовок сообщения:  Re: Кернинговые пары и вывод текста

Евгений Темиргалеев писал(а):
UNICODE = UCS2?
С некоторых пор уже UTF-16.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/