Арабский текст "присоединился" в Freetype
Мы используем Freetype для рендеринга отдельных символов в атлас текстуры, а затем рендеринга из этой текстуры на экран. Однако, когда мы визуализируем арабский язык, персонажи не соединяются так, как должны. Все они похожи на отдельных персонажей, расположенных рядом друг с другом. Если мы помещаем одни и те же символы в Блокнот, например, они соединяются, но если мы помещаем пробел между каждым арабским символом, они отделяются и снова выглядят как наш рендеринг. Если в Блокноте мы удалим пробелы, символы по обе стороны от удаленного пробела "изменятся" и объединятся. Очевидно, что сочетание символов, расположенных вместе, изменяет их внешний вид.
Итак, как мы можем получить объединенные слова на арабском языке с помощью freetype? Можем ли мы напечатать все "слово" в растровое изображение, используя Freetype, и он автоматически настроит глифы для объединения, или есть какой-то перевод, который мы можем применить к списку символов utf8, который преобразует их в новые символы utf8, которые соединяются когда рядом друг с другом?
Спасибо
Shaun
0 ответов
Весь процесс, на уровне, на котором работает Freetype (рендеринг глифов), описан, например, здесь. Как видите, это совсем не просто.
Существует (несколько) библиотека, расположенная поверх Freetype, цель которой сделать этот процесс "простым" или, по крайней мере, более простым; но они работают на более высоком уровне абстракции, поэтому вам, вероятно, нужно изменить свою парадигму. Harfbuzz - один из таких проектов, тесно связанный с Freetype.
Действительно, можно сделать упрощенную реализацию рендеринга арабского текста.
Сначала вам нужно разбить текст UTF8 на символы Unicode. Для получения дополнительной информации: https://en.wikipedia.org/wiki/UTF-8.
Когда у вас есть последовательность Unicode, вам необходимо определить порядок отображения. Для простого арабского текста вы можете предположить, что он идет справа налево, а когда вы сталкиваетесь с текстом или цифрами слева направо, вам нужно изменить направление. Направление символа зависит от его класса Bidi, который является столбцом 5 в UnicodeData.txt базы данных Unicode: https://www.unicode.org/reports/tr44/
Алгоритм Bidi общего назначения не является тривиальным, в частности потому, что можно вставлять символы Unicode, например, для встраивания текста слева направо. Там все подробно объясняется: http://www.unicode.org/reports/tr9/
После этого для арабского текста нужно определить лигатуры. Буквы соединяются вместе в зависимости от их типа соединения, определенного в столбце 3 файла ArabicShaping.txt (в базе данных Unicode). Например, если у вас есть буква типа L (соединение слева) справа от буквы типа R (соединение справа), то они соединятся вместе.
Алгоритм прост: для каждой арабской буквы определите тип ее присоединения. Если он может присоединиться, попробуйте найти буквы слева и справа и убедитесь, что их тип присоединения является дополнительным.
Обратите внимание, что это могут быть символы, не являющиеся арабскими буквами. Упомянутый ранее класс Bidi может помочь вам определить тип присоединения символа, если он не упоминается в ArabicShaping.txt. Если класс Bidi - это NSM (без пробелов) или если общий класс - Cf, то тип соединения - T (прозрачный), в противном случае - U (без соединения).
При проверке вправо и влево пропускайте символы типа T, пока не найдете другой тип или не дойдете до конца текста. Обратите внимание, что если вы реализуете алгоритм Bidi, вам нужно остановиться в конце изоляции Bidi.
Как только вы узнаете, присоединяется ли персонаж, вы можете определить его форму представления: начальную, среднюю, окончательную, изолированную. В UnicodeData.txt найдите его кодовую точку. Это будет символ (столбец 1), соответствующий данной презентации (столбец 6). Например, "<исходный> 067B" представлен как символ FB54. Таким образом, вы можете заменить его.
Есть особый случай для Лам, за которым следует Алеф. В этом случае персонажи объединяются. Например, "<изолированный> 0644 0622" представлен как символ FEF5. Обратите внимание, что вы можете встретить знаки без интервала между ними. Если вы не справитесь с ними, вы можете их выбросить. В противном случае вы можете сохранить информацию на потом.
На этом этапе вы можете преобразовать массив символов Юникода в строку UTF8 и нарисовать ее с помощью FreeType. Учтите, что метки без интервала будут размещены неправильно. Для этого вам нужно нарисовать каждого символа отдельно и определить положение меток.