Windows Terminal: улучшенная поддержка Юникода, font fallback, эмодзи

Jul 10, 2022 09:46

Начало: « Установил Windows Terminal».

В этом посте я коротко опишу одну из причин, по которой решил попробовать поработать с программой-«эмулятором терминала» «Windows Terminal» (wt.exe): улучшенная поддержка Юникода по сравнению с программой-«эмулятором терминала» «Windows Console» (conhost.exe). Я проведу небольшой тест и объясню его результаты. Тут, видимо, стоит отметить, что я работаю в операционной системе «Windows 10 Pro» (64-разрядной).

Тест

Для теста я создал текстовый файл «тест.txt» размером 56 байт в кодировке UTF-8 (одна из кодировок Юникода):



Как видно на вышеприведенной иллюстрации, файл «тест.txt» содержит следующий текст:

неудача: ❌, удача: ✔, удача: ✔️

Символы-эмодзи «❌» и «✔️» удобно использовать в консольных программах при выводе сообщений пользователю о неудачном или удачном результате, полученном программой, соответственно.

Также на вышеприведенной иллюстрации показано содержимое этого текстового файла в двоичном редакторе (он же - «шестнадцатеричный редактор» или «hex-редактор»).

Теперь выведем файл «тест.txt» в консоль в программе «Windows Console» и в программе «Windows Terminal». В обеих этих программах я буду использовать программу-оболочку «PowerShell» 7 версии (самой свежей на сегодня). В обеих этих программах буду использовать моноширинный шрифт «Cascadia Mono». Вот как это у меня выглядит:



На вышеприведенной иллюстрации сверху показана работа в программе «Windows Console», снизу - работа в программе «Windows Terminal».

Видно, что обе программы успешно справились с выводом букв в консоль в кодировке UTF-8 (одна из кодировок Юникода). То есть Юникод поддерживают обе программы. Однако, на вышеприведенной иллюстрации также видно, что программа «Windows Console» не справилась с выводом в консоль символов-эмодзи, в то время как программа «Windows Terminal» с этим успешно справилась. Это и есть та самая «улучшенная поддержка Юникода», о которой я писал ранее.

Объяснение результатов теста

Реализация поддержки Юникода - непростая задача. На данный момент в таблице Юникода содержится чуть меньше 150 тысяч символов. Ни один существующий шрифт не включает в себя все эти 150 тысяч символов. Обычно хороший шрифт содержит несколько тысяч или десятков тысяч символов. Например, использованный в тесте шрифт «Cascadia Mono» (этот шрифт разрабатывался компанией «Microsoft» параллельно с созданием программы «Windows Terminal», вышел в 2019 году и стал шрифтом по умолчанию для программы «Windows Terminal», он - моноширинный) содержит всего 1779 глифов (в том числе буквы русского и латинского алфавитов).

При этом шрифт «Cascadia Mono» не включает глифы символов-эмодзи «❌» (U+274C) и «✔️» (U+2714), поэтому программа «Windows Console» не может их отобразить в консоли, она просто не может найти нужные глифы в шрифте и показывает вместо них символ (пустой прямоугольник), заготовленный в шрифте для такого случая (случай отсутствия нужного глифа).

Font fallback

Однако, в операционных системах «Windows» для таких случаев придумали технологии, которые называются «font fallback» (по-русски «замена шрифта») и «font linking» (по-русски «связывание шрифтов»). Тут подробнее (на английском языке):

https://docs.microsoft.com/en-us/globalization/input/font-technology

Суть технологии «font fallback» (замена шрифта) в том, что если программа поддерживает эту технологию, то при отсутствии в шрифте нужных глифов эта программа использует для отображения нужных символов другой шрифт, в котором есть нужные глифы. Какой конкретно шрифт использовать для замены, прописано в реестре операционной системы «Windows». Эту цепочку замен шрифтов можно переопределить, это называется «font linking» (по-русски «связывание шрифтов»).

Я уже ранее писал о примерах работы этой технологии в браузерах (на примере «Microsoft Edge») и в редакторе кода «VS Code». Только раньше я не знал, что эта технология называется «font fallback» и что она определена на уровне операционной системы.

Например, для отображения символов-эмодзи «❌» (U+274C) и «✔️» (U+2714) в моей операционной системе программы обычно используют шрифт «Segoe UI Emoji», в котором есть глифы этих символов.

Программа «Windows Terminal» использует технологию «font fallback» (замена шрифта) и поэтому может отобразить указанные символы-эмодзи.

Почему же этого не может программа «Windows Console»? Как я понимаю, программа «Windows Console» была придумана задолго до появления технологии «font fallback» (замена шрифта) в разрезе отдельных символов (так-то замена шрифта целиком в случае отсутствия нужного шрифта практикуется довольно давно в языках HTML и CSS). Ее движок для отрисовки символов на экране компьютера устарел, он не может справиться с нужной заменой символов. Тут сложность еще в том, что в консолях обычно используются моноширинные шрифты, а символы из шрифта замены (fallback font) могут браться из не моноширинного шрифта. Чтобы правильно отобразить такие символы, от движка отрисовки (rendering engine) требуются дополнительные усилия, которых движок программы «Windows Console» не может обеспечить. Поэтому создали программу «Windows Terminal», в которой движок отрисовки символов абсолютно новый, и этот движок может справиться с технологией «font fallback» (замена шрифта), совместив заменяемые символы и моноширинный шрифт.

Режим отображения эмодзи

Про это у меня уже был отдельный пост.

Внимательный человек мог заметить на вышеприведенных иллюстрациях, что символ эмодзи с галкой в тестовом файле «тест.txt» у меня отображен в двух видах: «✔» (текстовый вид) и «✔️» (графический вид) соответственно.

В таблице Юникода это один и тот же символ - U+2714. Для отображения этого эмодзи в текстовом виде данный символ применяется «как есть», с кодом U+2714 (в кодировке UTF-8 этот код занимает три байта: E2 9C 94). Для отображения этого эмодзи в графическом виде к коду U+2714 следует добавить код символа U+FE0F (один из так называемых «селекторов начертания» в Юникоде), который в кодировке UTF-8 тоже занимает три байта: EF B8 8F. Таким образом, символ эмодзи «✔️» (в графическом виде) записывается в кодировке UTF-8 шестью байтами: E2 9C 94 EF B8 8F. Это можно проверить в первой иллюстрации в начале данного поста, где изображен двоичный редактор.

Для символа эмодзи «❌» (U+274C) таких сложностей не нужно: для его написания в кодировке UTF-8 достаточно трех байт: E2 9D 8C и он сразу будет отображен в графическом виде.

Почему существует эта разница? Дело в том, что разные символы эмодзи добавлялись в таблицу Юникода в разное время (в некоторых случаях разница между добавлением разных символов в таблицу составляет десятки лет). В разное время для символов определяли при их добавлении в таблицу Юникода разный режим отображения по умолчанию. Символ «✔️» (U+2714) был добавлен в таблицу Юникода в начале 90-х годов прошлого века, тогда режим отображения по умолчанию для символов был текстовым. Символ «❌» (U+274C) добавили в таблицу Юникода в 2010 году, когда режим отображения по умолчанию для эмодзи стал графическим. Отсюда разница.

Отследить, у каких символов эмодзи какой режим по умолчанию (текстовый или графический), можно по следующей ссылке:

https://unicode.org/emoji/charts-12.1/text-style.html

Ссылки на обсуждаемые символы эмодзи в таблице Юникода:

https://unicode-table.com/ru/274C/
https://unicode-table.com/ru/2714/
https://unicode-table.com/ru/FE0F/

Увеличим предыдущую иллюстрацию:



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

Также видно, что при отрисовке в программе «Windows Terminal» эмодзи с галкой в текстовом виде гораздо меньше эмодзи с галкой в графическом виде. Это происходит потому, что при отображении в текстовом виде символ эмодзи должен «влезть» в ячейку символа моноширинного шрифта. Поэтому движок отрисовки уменьшает глиф по ширине, а высота уменьшается пропорционально. Таким образом получается «уменьшение» эмодзи. В интернетах можно довольно часто встретить жалобы пользователей программы «Windows Terminal» на «уменьшенные» эмодзи. Решение их проблемы в том, что в данном случае эмодзи следует отобразить в графическом виде, тогда и размер будет такой, как ожидается.

Инструмент, Образование, Программирование, Английский язык

Previous post Next post
Up