> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/uk/dokladni-statti/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md).

# Огляд технологій, що підтримують використання кольорових шрифтів emoji в LaTeX

## Вступ

Ця стаття дає огляд різних [довідкових тем](#which-topics-do-we-cover) пов’язаних із використанням кольорових шрифтів OpenType для верстки кольорових емодзі в LaTeX. Ми намагалися надати широкий спектр матеріалів, що відповідають найрізноманітнішим інтересам і рівням підготовки. Щоб стаття залишалася керованою за обсягом, наше висвітлення деяких тем опускає багато технічних деталей, але ми сподіваємося, що матеріалу достатньо, щоб зорієнтувати вас у дослідженні верстки кольорових емодзі в LaTeX.

**Оновлення (липень 2023)**: Цю статтю вперше опубліковано в серпні 2021 року й переглянуто в липні 2023 року, щоб оновити розділ про [Використання кольорових шрифтів OpenType на основі SVG із LuaHBTeX](#using-svg-based-opentype-color-fonts-with-luahbtex).

### Які теми ми охоплюємо?

Ця стаття охоплює такі загальні теми:

* Unicode: стандарт, який кодує емодзі як символи та формалізує їхню очікувану поведінку в застосунках для обробки тексту й верстки.
* Кольорові шрифти OpenType: спеціалізовані шрифти, що надають барвисті зображення символів емодзі, які відображаються у вашому документі LaTeX.
* Формування тексту: ознайомлення з ключовим компонентом верстки мов із складними писемностями та емодзі.
* HarfBuzz: компонент LuaHBTeX, який дає змогу виконувати розширену багатомовну верстку та використовувати кольорові шрифти OpenType для верстки емодзі в LaTeX.
* Різні рушії TeX: дослідження їхньої підтримки кольорових шрифтів OpenType та вибір, який рушій TeX використовувати.
* API HarfBuzz у LuaHBTeX: вступ до «магії» за [формуванням тексту](#the-concept-of-text-shaping) у LuaHBTeX.

### Три способи верстати кольорові емодзі

Кольорові емодзі можна верстати в LaTeX трьома основними способами:

1. За допомогою стандартних графічних інструментів LaTeX, таких як TikZ, MetaPost або Asymptote, для малювання емодзі.
2. Вставляючи емодзі за допомогою підготовлених заздалегідь графічних зображень емодзі, що зберігаються в зовнішніх файлах.
3. Розглядаючи емодзі як текст, закодований Unicode, і використовуючи [формуванням тексту](#the-concept-of-text-shaping) з [кольорові шрифти OpenType](#opentype-color-fonts) для їхньої верстки.

Практичні варіанти включення кольорових емодзі у ваш документ LaTeX залежать від рушія TeX, який використовується для компіляції цього документа, тобто чи використовуєте ви:

* pdfLaTeX: рушій pdfTeX + LaTeX;
* XeLaTeX: рушій XeTeX + LaTeX;
* LuaLaTeX: рушій LuaHBTeX (починаючи з TeX Live 2020) + LaTeX.

Усі три ці рушії TeX можуть використовувати інструменти або пакети LaTeX для малювання емодзі або використання `\includegraphics{...}` для вставлення емодзі, збережених у зовнішніх графічних файлах. Малювання або імпорт графіки — ідеальні способи верстки емодзі, коли вам потрібне рішення, яке не залежить від рушія TeX, що використовується для компіляції документа LaTeX.

Однак, якщо ваш робочий процес дає змогу обрати конкретний рушій TeX і ви віддаєте перевагу використанню кольорових шрифтів OpenType та обробки тексту на основі Unicode, вам потрібна найновіша версія LuaTeX, яка називається LuaHBTeX. Починаючи з TeX Live 2020, LuaHBTeX використовується для компіляції документів LaTeX на основі формату LuaLaTeX.

## Довідка про символи Unicode та емодзі

### Кодування символів

Комп’ютери зберігають, передають і обробляють текст, використовуючи послідовність числових (цілих) значень, що представляють складові тексту *символи*. Надійна обробка тексту вимагає, щоб виробники та споживачі тексту домовилися, які цілі числа слід використовувати для представлення окремих символів у потоці тексту. Іншими словами, яке *символа* *кодування* цього тексту?

### Кодування — це набір узгоджених цілих значень, призначених для представлення певного набору символів: кожен символ представлено цілим значенням у межах використовуваного кодування.

Історично, в епоху 8-бітного тексту, використовувалося багато різних кодувань символів, що постійно породжувало привид *невідповідностей кодування*: виробники та споживачі тексту помилково припускали різні кодування, що призводило до помилок обробки тексту. Кожен, хто протягом кількох років працював із TeX/LaTeX, імовірно, стикався з невідповідностями кодування між вхідним текстом і шрифтами, які використовувалися для верстки документа. Якщо шрифти документа налаштовані на використання кодування, відмінного від кодування тексту, це, ймовірно, призводить до відсутніх або помилкових символів у зверстаному PDF.

Ці історичні проблеми кодування можна розв’язати за допомогою міжнародного стандарту, що кодує всі символи світу: Unicode. Стандарт Unicode не є статичним, а періодично оновлюється, щоб включати додаткові символи та писемності (системи письма) до своєї схеми кодування. Існує [формальна процедура розгляду пропозицій щодо нових символів](http://www.unicode.org/pending/proposals.html) із окремою [схемою для нових символів емодзі](https://www.unicode.org/emoji/proposals.html).

### Скільки символів Unicode?

Unicode кодує теоретичний максимум 1 114 112 символів. Кожне з 1 114 112 цілих значень називається *кодова позиція*: цілим значенням, призначеним для ідентифікації кожного символу. Однак з різних технічних причин лише [1 112 064 кодові позиції](https://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology) можуть бути призначені реальним символам: 2048 кодових позицій не можна призначати й заборонено використовувати в тексті, сумісному з Unicode.

На момент написання (першої версії цієї статті) у Версії 13 стандарту Unicode загалом було призначено 143 859 кодових позицій реальним символам, включно з [3304 символами, які тепер закодовано як емодзі](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (див. сторінку 2 того документа). Зростання кількості символів, закодованих Unicode, добре задокументовано в статті [Скільки існує символів Unicode?](https://www.babelstone.co.uk/Unicode/HowMany.html) та в [статті Вікіпедії](https://en.wikipedia.org/wiki/Unicode#Versions).

### Площини Unicode

Вся сукупність із 1 114 112 кодових позицій Unicode згрупована в 17 так званих площин: від Площини 0 до Площини 16, кожна з яких містить 65 536 значень кодових позицій, що дає загалом $$17\times2^{16} = 1,114,112$$ символів. Площина 0, яка називається [Базова багатомовна площина](https://en.wikipedia.org/wiki/Plane_\(Unicode\)#Basic_Multilingual_Plane), кодує найуживаніші символи. Площини 1–16 називаються [Додаткові площини](http://unicode.org/glossary/#supplementary_planes).

### Піднесення емодзі

Нові символи виникають через зміну способів людського спілкування, і мобільні телефони спричинили появу одного такого набору символів: емодзі, які еволюціонували в Японії наприкінці 1990-х років. Не дивно, що [FAQ Unicode про емодзі](https://unicode.org/faq/emoji_dingbats.html) зазначає

> «Слово emoji походить від японських [絵](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E7%B5%B5) (e ≅ зображення) + [文字](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E6%96%87) (moji ≅ написаний символ).»

Читачам, яким цікаве тло та історичний розвиток емодзі, може бути цікава ця [вступна стаття про Unicode](https://unicode.org/reports/tr51/#Introduction) або стаття [Я теж за це емодзі: стандарти, структури та соціальне виробництво емодзі](https://firstmonday.org/ojs/index.php/fm/article/view/9381).

Лише у 2010 році, з випуском [версії 6.0 стандарту Unicode](https://www.unicode.org/versions/Unicode6.0.0/), багато емодзі було офіційно визнано як *символи* самостійні символи. У Unicode 13.0 закодовано [3304 символи як емодзі](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (див. сторінку 2 того документа), а в Unicode 13.1 наведено [3521 емодзі](https://unicode.org/emoji/charts/emoji-counts.html).

### Емодзі живуть на вищій площині

Unicode призначив багато символів емодзі кодовим позиціям за межами Базової багатомовної площини (BMP), закодованим [у Площині 1](https://en.wikibooks.org/wiki/Unicode/Character_reference/1F000-1FFFF) з кодовими позиціями в діапазоні 1F000–1FFFF, що має важливий наслідок для кожного, хто хоче *копіювати й вставляти* символи емодзі у редактори Overleaf (Code Editor або Visual Editor). Текстові редактори Overleaf наразі можуть обробляти лише символи в межах Базової багатомовної площини, хоча ми сподіваємося, що майбутні оновлення запровадять підтримку символів поза BMP. Зверніть увагу, що це обмеження стосується лише символів поза BMP у тексті, вставленому у файли, призначені для редагування через редактори Overleaf. Є й інші способи доступу до символів емодзі:

* Використання примітивних команд `\char\"<код позиції>` або `\Uchar\"<код позиції>` (див. [цей розділ](#optional-detail-luatexluahbtex-char-vs-uchar) статті).
* Використання вхідних текстових файлів, що містять символи емодзі у форматі UTF-8.
* Використання команд LaTeX (макросів), які вставляють символи емодзі.

#### Вставляння емодзі та інших символів поза BMP в Overleaf

Якщо ви вставите символ емодзі, наприклад 😀, у Overleaf Code Editor, він наразі буде перетворений на символи ��.

![Помилка через копіювання + вставлення символів поза BMP у редактори Overleaf](/files/945677f8b460f3b61d06af336dc9593224e23772)

Символ � має кодову позицію Unicode FFFD, а його офіційна назва — REPLACEMENT CHARACTER, і він використовується, щоб «[замінити невідомий, нерозпізнаний або непредставний символ](https://en.wikipedia.org/wiki/Specials_\(Unicode_block\))».

### Використання кодових позицій Unicode (U+) у LuaLaTeX

Документація Unicode подає значення кодових позицій у нотації `U+<шістнадцяткове значення>`— такі як `U+1F600`, де `1F600` це `<шістнадцяткове значення>` кодової позиції Unicode для символу емодзі 😀. Щоб використовувати ці значення кодових позицій у LuaLaTeX, ви видаляєте `U+` і пишете `\char\"<шістнадцяткове значення>` або `\Uchar\"<шістнадцяткове значення>`. `"` символ вказує рушію TeX, що надане число задано у шістнадцятковій системі. Наприклад, щоб використати емодзі 😀, ви б написали `\char\"1F600` або `\Uchar\"1F600`— використовуючи шрифт, здатний його верстати.

Мінімальний приклад LuaLaTeX із використанням `\char` та `\Uchar` для верстки символу емодзі 😀 може бути таким:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz]{NotoColorEmoji.ttf}
%Використовуйте \emojifont у групі, щоб зберегти локальність її дії
{\emojifont
\Uchar\"1F600
\char\"1F600}
\end{document}
```

[Відкрийте цей приклад LuaLaTeX в Overleaf](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Test+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%5D%7BNotoColorEmoji.ttf%7D%0A%25Use+%5Cemojifont+in+a+group+to+keep+its+effects+local%0A%7B%5Cemojifont+%0A%5CUchar%221F600%0A%5Cchar%221F600%7D%0A%5Cend%7Bdocument%7D)

**(необов’язкова деталь) LuaTeX/LuaHBTeX: \char vs \Uchar**

На додаток до звичайної `\char<character code>` команди для верстки певного `<код символу>`, використовуючи поточний шрифт, рушії LuaTeX, LuaHBTeX і XeTeX також надають `\Uchar<character code>` команду. З точки зору користувача, результат `\char` та `\Uchar` виглядає однаково, але в тому, як ці команди працюють, є тонка різниця, як ми зазначаємо нижче.

**Ключова різниця: розгортання**

`\Uchar` є так званою [розгортуваною командою](/latex/uk/dokladni-statti/22-how-does-expandafter-work-the-meaning-of-expansion.md#expansion-a-general-term-for-a-set-of-operations) тоді як `\char` не є розгортуваною. Коли `\char<character code>` або `\Uchar<character code>` команда «виконується», тобто команда не зберігається як частина макроса або іншого списку токенів, у рушії TeX відбуваються такі дії:

* **`\char<character code>`** наказує рушію TeX негайно вставити токен символу, що представляє `<код символу>`, у той фрагмент вмісту, який він наразі верстатиме.
* Натомість, **`\Uchar<character code>`** має два окремі кроки обробки:

1. Функція `\Uchar<character code>` команда *розгорнуто*є `<код символу>` , а [символьним токеном](/latex/uk/dokladni-statti/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#tex-tokens-101-28and-notions-of-expansion29) перетворюється на тимчасовий список токенів, що містить один `<код символу>`.
2. який представляє *Цей список із одного токена тепер* надано рушію TeX як джерело його наступного введення. По суті, рушій TeX «тимчасово переводить погляд», щоб використовувати цей список із одного токена як місце свого наступного елемента введення (токена). За замовчуванням рушій TeX просто повертається, щоб прочитати (ввести) цей токен і верстати відповідний символ, відтворюючи поведінку `\char` команду. **Однак**, оскільки цей `<код символу>` не був одразу зверстаний, а тимчасово *зберігаються* (збережений) як один токен, примітивні команди TeX або макроси LaTeX можуть використати (поглинути) цей токен — його не обов’язково верстати негайно, але за потреби можна використати в подальшій обробці.

По суті, `\char<character code>` каже: «верстай це `<код символу>` зараз», тоді як `\Uchar<character code>` має форму «відкладеної дії», створюючи збережений токен символу й роблячи його доступним як наступний елемент введення (токен). Цей токен можна або використати (поглинути) командами та макросами TeX, або повторно прочитати рушієм TeX і зверстати.

### Unicode (кодування) — це ще не вся історія

Можливість використовувати символи емодзі в тексті, закодованому Unicode, — лише частина історії успіху емодзі. Сплеск використання емодзі також став можливим завдяки розвитку [технології шрифтів OpenType](https://learn.microsoft.com/en-us/typography/opentype/)— шрифтів, чиї гліфові дані (дизайни символів) можуть містити [кольорові дані](https://learn.microsoft.com/en-us/typography/opentype/spec/colr): так звані [кольорові шрифти OpenType](#opentype-color-fonts).

Окрім відповідних шрифтів, використання кольорових емодзі потребує додаткових програмних компонентів, чиї завдання включають:

* попередню обробку («[формування](#the-concept-of-text-shaping)») тексту, закодованого Unicode, *підготовку* його до відображення за допомогою певного шрифту;
* *візуалізацію та відображення* кольорових емодзі шрифту *гліфів* на екрані пристрою.

#### Гліф і символ: хіба це не одне й те саме?

Терміни «гліф» і «символ» часто використовуються так, ніби вони взаємозамінні — як позначення однієї й тієї самої базової концепції — але в їхньому значенні є тонка, хоч і важлива, різниця.

Unicode [визначає термін «символ»](http://www.unicode.org/glossary/#character) як:

> «Найменший компонент писемної мови, що має семантичну цінність; стосується абстрактного значення та/або форми, а не конкретної форми…»

Натомість «гліф» — це *конкретний* *форма* (дизайн) для *візуального відображення* певного *символа*.

Питання символу проти гліфа легко помітити, коли текст, насичений емодзі, переглядають у різних програмних системах/платформах, наприклад читаючи той самий текст на мобільному телефоні з iOS чи Android або на настільному комп’ютері Windows. Який би пристрій або платформу не використовували, базовий текст (послідовність символів) містив би ті самі символи емодзі, закодовані в Unicode *емодзі* *символи*. Саме можливості конкретного пристрою, пов’язані з *попередньою обробкою* цього тексту, а потім *візуалізацією* та *відображувальному* результатів, можливо з використанням шрифтів конкретного пристрою, створюють різні гліфи (дизайни символів) для представлення тих самих символів емодзі.

Повний список емодзі Unicode [надає зразки зображень, що представляють кожен символ емодзі Unicode, демонструючи різні гліфи, які використовують різні технологічні виробники. Не лише дизайнери шрифтів застосовують власні особливі дизайни (гліфи) для представлення символів емодзі, але й окремі шрифти відрізняються кількістю символів емодзі, які вони підтримують (для яких містять гліфи), і можуть або не можуть містити більш просунуті можливості обробки тексту емодзі, включені до специфікацій Unicode для емодзі.](https://unicode.org/emoji/charts/full-emoji-list.html) Поняття й концепція символів, їхня семантика та кодування є основою світу Unicode: він має справу зі символами. Дизайн і візуальне представлення окремих символів як гліфів належать до технологій шрифтів і ремесла дизайну шрифтів.

Емодзі Unicode: набагато більше, ніж кодування тексту

#### Ключова роль Unicode полягає в тому, щоб надати глобальний стандарт кодування, який визначає, яке ціле значення, що називається

кодова позиція, *слід використовувати для представлення кожного символу, включно з емодзі, у потоці тексту, закодованого Unicode.* Специфікація Unicode для емодзі також визначає

поведінку обробки *для певних* символів емодзі, що з’являються в потоці тексту, закодованого Unicode. Визначені послідовності символів емодзі можуть бути «об’єднані» через процес, який називається *послідовності* щоб утворити один підсумковий («композитний») гліф емодзі — цей один гліф операційна система пристрою використовувала б для представлення початкової послідовності символів, наявної в тексті. [формуванням тексту](#the-concept-of-text-shaping) Технічний звіт Unicode про

Unicode Emoji [документує багатий набір можливостей, доступних програмному забезпеченню, яке прагне забезпечити обробку символів емодзі відповідно до Unicode. Наприклад, Unicode визначає (кодує) символи, які називаються](https://unicode.org/reports/tr51/) модифікатори емодзі [які можна використовувати для створення](http://www.unicode.org/reports/tr51/#Emoji_Modifiers_Table) варіацій *«базових» символів емодзі, таких як варіації* кольору шкіри на основі шкали Фіцпатріка [. Зверніть увагу, що набір базових символів емодзі та застосовні модифікатори визначено як частину загального](http://www.unicode.org/reports/tr51/#Diversity)стандарту Unicode для емодзі [Сторінка Unicode](http://www.unicode.org/reports/tr51).

Послідовності емодзі [надає таблицю послідовностей, які наразі передбачені специфікацією Unicode. Наведіть вказівник миші на будь-яке зображення гліфа емодзі, щоб побачити невеликий підказковий спливаючий текст, який показує базову послідовність символів емодзі Unicode, що створює цей гліф:](http://unicode.org/emoji/charts/emoji-sequences.html) EmojiSequenceChart.png

![Наприклад, гліф емодзі:](/files/603de7c1cbbf57d060755a085a1bdfa25835f761)

HandMediumSkinTone.png

![перелічено в](/files/3919c6afbe58154da73d504ca54ea087da535d25)

розділі послідовностей модифікаторів [і створюється двосимвольною послідовністю U+1F44B U+1F3FD. Ці складові символи є:](http://unicode.org/emoji/charts/emoji-sequences.html#modifier_sequences) U+1F44B:

(МАХАННЯ РУКОЮ)![UnicodeWavingHandDefault.png](/files/b9614af9b1fc43d2278dc4826106ead6cae85005) U+1F3FD:

(МОДИФІКАТОР ЕМОДЗІ FITZPATRICK ТИПУ-4)![FitzPatrick3.png](/files/8e0f85eaabf933eeb6fd03282af0d25c69c5a8ce) Використання модифікаторів тону шкіри в LuaHBTeX

**Наступний приклад використовує LuaHBTeX, щоб продемонструвати використання модифікаторів емодзі:**

\newfontfamily\emojifont\[Renderer=HarfBuzz,SizeFeatures={Size=20}]{NotoColorEmoji.ttf}

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
Окрема помахуюча рука: {\emojifont\Uchar\"1F44B}\par
Окремий модифікатор: {\emojifont\Uchar\"1F3FD}\par
Поєднаний результат: {\emojifont\Uchar\"1F44B\Uchar\"1F3FD}
Відкрийте цей приклад модифікаторів емодзі LuaLaTeX в Overleaf
\end{document}
```

[ModifiersInLuaHBTeX.png](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Emoji+modifiers+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfBuzz%2CSizeFeatures%3D%7BSize%3D20%7D%5D%7BNotoColorEmoji.ttf%7D%0AIsolated+waving+hand%3A+%7B%5Cemojifont%5CUchar%221F44B%7D%5Cpar%0AIsolated+modifier%3A+%7B%5Cemojifont%5CUchar%221F3FD%7D%5Cpar+%0ACombined+result%3A+%7B%5Cemojifont%5CUchar%221F44B%5CUchar%221F3FD%7D%0A%5Cend%7Bdocument%7D)

Цей приклад дає такий результат:

![UTF-8: його роль у зберіганні тексту Unicode](/files/4f254abad373e4907a43ff5ae7203df450d95257)

#### Будь-який текст або код, який ви вводите чи вставляєте в Code Editor Overleaf (або Visual Editor), зберігатиметься у форматі UTF-8, тож ми коротко розглянемо, що саме означає UTF-8. UTF розшифровується як Unicode Transformation Format, а роль UTF-8 у зберіганні або передаванні тексту, закодованого Unicode, вказується фразою «перетворення

формат *».*&#x417;начення кодових позицій Unicode лежать у діапазоні від 0 до максимуму 1 114 111, тож неможливо представити всі значення символів Unicode за допомогою одного 8-бітного байта, який може зберігати лише до 256 різних значень: від 0 до 255. Однак будь-яке ціле значення кодової позиції Unicode можна представити за допомогою

послідовності *байтових значень, що слідують одне за одним — саме в цьому полягає принцип UTF-8.* UFT-8 надає «рецепт» для

перетворення *(тобто для «кодування» або «конвертування») цілого значення кодової позиції Unicode в унікальну послідовність із 1 до 4 послідовних байтових цілих значень: кількість послідовних байтів, які потрібні, залежить від значення цілого числа кодової позиції. Відтак ви можете зустріти згадку, що UTF-8 зберігає символи Unicode як* багатобайтові послідовності *оскільки один символ Unicode (ціле значення кодової позиції) у UTF-8 подається як послідовність із 1 до 4 послідовних байтів.* Звісно, текст, збережений у UTF-8, можна перетворити назад на його початкову послідовність цілих значень кодових позицій Unicode — саме це мають робити XeTeX або LuaTeX/LuaHBTeX, читаючи вхідний файл LaTeX, збережений у форматі UTF-8. Ці рушії TeX повинні знати значення вхідних кодових позицій Unicode (символів), перш ніж вони зможуть верстати текст. Зверніть увагу, що pdfTeX не має вбудованої можливості декодування UTF-8, тому він мусить покладатися на макроси TeX для обробки (декодування) вхідного тексту, відформатованого в UTF-8.

Деякі приклади UTF-8

**Арабський символ ش («шин») має кодову позицію Unicode 0634 у шістнадцятковій системі (основа 16) або 1588 у десятковій системі (основа 10). У UTF-8 ش подається 2 (шістнадцятковими) значеннями D8 і B4, тож символ ش зберігався б як два послідовні байти D8B4 у тексті, закодованому UTF-8.**

* Символ емодзі 😀 має кодову позицію Unicode 1F600 у шістнадцятковій системі (основа 16) або 128512 у десятковій системі (основа 10). У UTF-8 😀 подається 4 (шістнадцятковими) значеннями F0, 9F, 98 і 80, тож символ 😀 зберігався б як 4 послідовні байти F09F9880 у текстовому файлі UTF-8.
* Спеціальні символи, що використовуються в обробці тексту емодзі на основі Unicode

#### Не кожен символ, закодований у Unicode, призначений для візуального подання через гліфи в шрифті: деякі закодовані символи позначено як

недруковані символи *призначення яких — допомагати спеціалізованим функціям обробки тексту (у підтримувальному програмному забезпеченні). Різні програмні застосунки надають різні рівні підтримки недрукованих символів, закодованих у Unicode, тож результат залежатиме від програмного середовища — застосунків і шрифтів, що використовуються.* Два недруковані символи, про які слід знати

**Нульовий пробіл-з’єднувач (ZWJ)**

* **, кодова позиція 200D (шістнадцяткова), як випливає з назви, призначений для запуску «поведінки з’єднання» вхідних символів — але лише якщо ці вхідні символи**мають *визначену поведінку з’єднання.* Нульовий пробіл-роз’єднувач (ZWNJ)
* **, кодова позиція 200C (шістнадцяткова), призначений для**пригнічувати *запобігти* «поведінку з’єднання», яку вхідні символи могли б інакше проявляти. Наприклад, ви можете використати ZWNJ, щоб запобігти поведінці з’єднання послідовних арабських символів, які зазвичай обробляються (формуються) у їхні з’єднувальні форми.

Unicode опублікував список [рекомендованих послідовностей емодзі ZWJ](https://unicode.org/emoji/charts/emoji-zwj-sequences.html) які використовують U+200D ZERO WIDTH JOINER (ZWJ) для поєднання послідовностей символів емодзі в один складений гліф емодзі — якщо він доступний у використовуваному(-их) шрифті(-ах).

**Приклад використання нульового пробілу-роз’єднувача**

Наведений нижче мінімальний фрагмент коду використовує шрифт Scheherazade OpenType, що входить до складу TeX Live, щоб визначити шрифт LaTeX під назвою `\arabicfont` який ми можемо використовувати для верстки арабського тексту. Рядок

```latex
{\arabicfont Non-joining:\textdir TRT\Uchar\"0644\Uchar\"200C\Uchar\"0627}
```

використовує символ нульового пробілу-роз’єднувача через `\Uchar\"200C`, щоб запобігти звичайній поведінці з’єднання двох арабських літер ل (лам) і ا (аліф). Зверніть увагу на використання `\textdir TRT` для встановлення напряму тексту справа наліво:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\arabicfont[Script=Arabic,Renderer=Harfbuzz,SizeFeatures={Size=40}]{Scheherazade}
{\arabicfont Joining:\textdir TRT\Uchar\"0644\Uchar\"0627}\par
{\arabicfont Non-joining:\textdir TRT\Uchar\"0644\Uchar\"200C\Uchar\"0627}
\end{document}
```

[Відкрийте цей приклад LuaLaTeX в Overleaf](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Zero+width+non-joiner+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Carabicfont%5BScript%3DArabic%2CRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D40%7D%5D%7BScheherazade%7D%0A%7B%5Carabicfont+Joining%3A%5Ctextdir+TRT%5CUchar%220644%5CUchar%220627%7D%5Cpar%0A%7B%5Carabicfont+Non-joining%3A%5Ctextdir+TRT%5CUchar%220644%5CUchar%22200C%5CUchar%220627%7D%0A%5Cend%7Bdocument%7D)

Цей приклад дає такий результат:

![NonJoiner.png](/files/9108c95fbaf743ff6bfda8f09ffed7bb18fa0f24)

## Поняття «формування тексту»

Почнімо з візуального прикладу, використовуючи урду-переклад слова «educational». Текст урду-перекладу можна було б набрати на клавіатурі чи сенсорному пристрої, і він був би створений як проста лінійна послідовність символів арабської писемності Unicode. Однак, коли цей текст верстається або відображається на екрані пристрою в стилі [насталік](https://en.wikipedia.org/wiki/Nastaliq), результатом є складне двовимірне розташування гліфів.

Використовуючи наш приклад урду, наведена нижче графіка порівнює лінійний вхід арабського Unicode *символи* з результатом, зверстаним у стилі насталік, що складається з двовимірного розташування *гліфів* наявних у (безплатному) шрифті [Awami Nastaliq](https://software.sil.org/awami/download/):

![](/files/f98ac7d0a73b51a8bea82e11ab49b9bcfbb13d8b)

Процес «перекладу» вхідних символів у набір правильно розташованих вихідних гліфів називається *формуванням тексту*і є життєво важливим компонентом обробки тексту перед його відображенням або версткою. Наш приклад використовував текст мовою урду (арабська писемність), тому що результат формування тут добре помітний, на відміну від мов, що використовують латинську писемність, таких як англійська, де формування виражене набагато менше — наприклад, у вигляді простих лігатур.

Формування тексту є необхідним під час використання писемностей (систем письма), таких як [Арабська](https://en.wikipedia.org/wiki/Arabic), [іврит](https://en.wikipedia.org/wiki/Hebrew_language), [деванагарі](https://en.wikipedia.org/wiki/Devanagari) або [малаялам](https://en.wikipedia.org/wiki/Malayalam), лише чотири приклади так званих *складних писемностей*. Щоб забезпечити правильне відображення тексту в цих писемностях і мовах, які їх використовують, процес формування має ретельно враховувати будь-які правила й нюанси формування, наявні у конкретній комбінації писемності та мови. Наприклад, деякі мови вимагають, щоб кілька вхідних символів утворювали певний вихідний гліф, або можуть існувати складні вимоги до ретельного розташування діакритичних знаків та взаємного переставляння гліфів, щоб забезпечити правильне положення окремих гліфів (відносно один одного).

Загалом формування фрагмента тексту потребує кількох відомостей:

* Система письма або *писем* у якій написано текст.
* Конкретна *мови* що використовується. Окремі писемності можуть використовуватися для кількох мов, причому кожна комбінація писемності й мови має свої особливості/нюанси формування.
* Писемність *напрям* тексту — наприклад, справа наліво або зліва направо.
* Скопійований *шрифт* який надає гліфи, потрібні для відображення сформованого тексту, і, за потреби, містить додаткові «правила формування», що керують процесом формування тексту.

Вимоги до формування тексту, особливо для складних писемностей і пов’язаних із ними мов, можуть бути надзвичайно детальними й тонкими, що вказує на потребу в спеціалізованому програмному забезпеченні, яке може застосовувати потенційно дуже складні «правила» формування тексту. Не дивно, що таке програмне забезпечення існує і називається *рушій формування тексту*; той, який ми розглянемо, називається [HarfBuzz](https://en.wikipedia.org/wiki/HarfBuzz), документацію якого варто прочитати — наприклад [Навіщо мені потрібен рушій формування тексту?](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html).

**Додаткове читання про формування тексту**

Ці короткі вступи дуже рекомендовані:

* [Що таке формування тексту?](https://harfbuzz.github.io/what-is-harfbuzz.html#what-is-text-shaping)
* [Навіщо мені потрібен рушій формування тексту?](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html)

**Технічна примітка: кілька технологій формування (моделей)**

Рушій формування тексту HarfBuzz підтримує кілька «технологій формування», які відрізняються способом реалізації процесу формування — кожну реалізацію називають *шейпером*, зокрема в `luaotfload` документації. Основна увага цієї статті зосереджена на формуванні OpenType, але альтернативною, безкоштовною технологією є [Graphite](https://scripts.sil.org/cms/scripts/page.php?site_id=projects\&item_id=graphite_aboutOT), розроблена [SIL International](https://www.sil.org/). Інша модель формування, яку підтримує HarfBuzz, — це [Apple Advanced Typography (AAT)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html)— шрифти, що підтримують AAT, зазвичай використовують на технологічних платформах Apple.

**Приклад використання шейпера Graphite**

У наведеному нижче прикладі набирається певний урду-текст за допомогою шрифту під назвою [Awami Nastaliq](https://software.sil.org/awami/download/), який підтримує формування Graphite і доступний в Overleaf. Awami Nastaliq створено [SIL International](https://www.sil.org/), організацією, що відповідає за розробку технології Graphite.

Наведений нижче приклад демонструє розширені можливості формування шрифтів на основі Graphite — зверніть увагу, як `luaotfload` оголошення шрифту вибирає формування Graphite за допомогою `shaper=graphite2`.

```latex
\documentclass{article}
\usepackage{luaotfload}
\begin{document}

\font\urdutest={file:AwamiNastaliq-Regular.ttf:mode=harf;shaper=graphite2} at 100bp
% Технологія
\pardir TRT\textdir TRT \urdutest ٹیکنالوجی

\vskip 75bp

% Освітній
\pardir TRT\textdir TRT \urdutest تعلیمی
\end{document}
```

[Відкрийте цей приклад в Overleaf.](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+Urdu+using+the+Graphite+shaper\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bluaotfload%7D%0A%5Cbegin%7Bdocument%7D%0A%0A%5Cfont%5Curdutest%3D%7Bfile%3AAwamiNastaliq-Regular.ttf%3Amode%3Dharf%3Bshaper%3Dgraphite2%7D+at+100bp%0A%25+Technology%0A%5Cpardir+TRT%5Ctextdir+TRT+%5Curdutest+%D9%B9%DB%8C%DA%A9%D9%86%D8%A7%D9%84%D9%88%D8%AC%DB%8C%0A%0A%5Cvskip+75bp%0A%0A%25+Educational%0A%5Cpardir+TRT%5Ctextdir+TRT+%5Curdutest+%D8%AA%D8%B9%D9%84%DB%8C%D9%85%DB%8C%0A%5Cend%7Bdocument%7D)

Цей приклад дає такий результат:

![](/files/0126f59276846b5d92a8da247e13329b0557d6c8)

#### Емодзі та формування тексту

Формування тексту було введено на прикладах мови зі складною писемністю, урду. Однак може здивувати те, що для відображення правильних гліфів емодзі потрібно застосовувати формування тексту до Unicode-тексту, що містить послідовності символів емодзі —[як зазначив провідний розробник HarfBuzz](https://github.com/harfbuzz/harfbuzz/issues/2428#issuecomment-639108677):

> ...формування емодзі в HarfBuzz цілком входить у сферу застосування і фактично необхідне для отримання сімейних емодзі, відтінків шкіри тощо.

Ми розглянемо приклади цього.

### Розподіл відповідальності: рушій формування тексту + шрифти OpenType

На практиці формування тексту — це «спільна операція», або поділ праці, між логікою та правилами, вбудованими в рушій формування тексту, і додатковими правилами та даними формування, вбудованими у використовуваний(-і) шрифт(-и) — далі ми розглядатимемо лише формування на основі OpenType *лише*.

Для виконання формування рушію формування тексту зазвичай передають певний Unicode-текст, вказане письмо й мову, можливо, напрям письма, і, що найважливіше, шрифт OpenType для використання під час процесу формування — шрифт надаватиме результат: набір гліфів і дані позиціювання. Якщо потрібно, рушій формування може застосовувати додаткові правила ([функції OpenType](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features)) що містяться у використовуваному шрифті OpenType, — які правила застосовувати, зазвичай можна вибрати користувачеві зі списку функцій, що підтримуються шрифтом.

Результатом процесу формування є *список гліфів* що містяться в шрифті OpenType, разом із *міжгліфовими* даними позиціювання. Ці дані позиціювання стосуються *відносного розташування сформованих гліфів*; вони не стосуються абсолютного розташування на набраній сторінці чи в іншому носії/контенті, такому як вебсторінка, твіт тощо. Програмне забезпечення для візуалізації (рушій набору, веббраузер тощо) використовує інформацію про міжгліфове позиціювання, щоб забезпечити правильне взаємне розташування гліфів після їх складання та включення в кінцевий результат.

#### Що таке список гліфів?

Усередині кожному гліфу в шрифті OpenType призначається числовий ідентифікатор, ціле значення, яке називається індексом гліфа — також glyph identifier або GID. Після завершення своєї задачі формування рушій формування тексту поверне результати як *список ідентифікаторів гліфів* плюс *дані позиціювання* для цих гліфів.

Окремим гліфам у шрифтах OpenType їхній автор призначає індекси (ідентифікатори), тож це дуже специфічне для шрифту й довільне значення — воно також може відрізнятися між версіями певного шрифту. Ніколи не слід припускати, що те саме значення GID застосовуватиметься до «схожих» гліфів у різних шрифтах; майже напевно це не так. Якщо у вас є список ідентифікаторів гліфів, наданий рушієм формування, ви можете використовувати їх лише для доступу до гліфів у тому шрифті, з якого їх було отримано.

#### Що таке шрифти OpenType?

У мережі *безліч* пояснень і деталей про шрифти OpenType, тож ми обмежимося коротким описом. Ця [специфікація OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/) є складним документом, призначеним для розробників, але по суті він визначає формат файлу, або контейнер, для даних шрифту. Шрифт OpenType містить дані, що описують форми гліфів, разом із відомостями про підтримувані письма та мови, метаданими про шрифт і різними «таблицями», які визначають [типографічні функції](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features) що підтримуються шрифтом.

Рушієві формування тексту зазвичай можна вказати вибірково застосовувати (використовувати) функції шрифту під час процесу формування, застосовуючи певні типографічні ефекти («правила»), які добирають відповідний набір гліфів, що містяться у шрифті. Обраний шрифт має підтримувати й надавати гліфи для будь-яких функцій, які рушій формування тексту має застосувати.

#### Закодовані та незакодовані «гліфи»

Шрифти OpenType містять таблицю даних під назвою [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) (Character to Glyph Index Mapping), яка відображає набір символів Unicode, підтримуваних шрифтом, у відповідний індекс гліфа в цьому шрифті. Наступне відео дає короткий погляд на таблицю cmap, що міститься у шрифті під назвою `lmmono10-regiular.otf` (включено до TeX Live).

{% embed url="<https://videos.ctfassets.net/nrgyaltdicpt/2537Y9gOUMWgd0t1guqt0X/482c53a9d8112ecae3d622aa7e00eef8/openType_cmap.mp4>" %}

Однак шрифти зазвичай містять багато гліфів, які не представляють певного символу Unicode і не входять до цієї таблиці cmap. Відповідно, набір гліфів у шрифті OpenType можна поділити на два основні набори:

* закодовані гліфи, що представляють символи Unicode;
* незкодовані гліфи, що не представляють символи Unicode.

До закодованих гліфів можна отримати доступ, включивши відповідний символ Unicode в текст — але як щодо незкодованих гліфів, як вони використовуються/доступаються? Такі гліфи зазвичай використовуються для формування результату операцій формування тексту, зокрема застосування функцій шрифту для створення певних візуальних/типографічних ефектів.

### кольорові шрифти OpenType

Очікується, що символи емодзі відображатимуться у повному кольорі — чорно-білі емодзі не зовсім забезпечують «повноцінний досвід емодзі». Однак на момент початкового кодування емодзі в Unicode [специфікація шрифтів OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/) не мала жодного придатного механізму для вбудовування *colorful*-гліфових даних у шрифтах OpenType. Ця «прогалина» в OpenType спонукала провідних постачальників технологій/платформ шукати рішення, і подальша «гонка» призвела до [різних пропозицій щодо розширення OpenType](https://www.fontlab.com/news/color-font-format-proposals/) для підтримки кольорових шрифтів OpenType — не лише для відображення кольорових символів емодзі (гліфів), а й для відтворення будь-якого гліфа в кольорі.

#### Чотири різновиди кольорових шрифтів OpenType

[Adobe, Microsoft, Google і Apple подали свої пропозиції](https://www.fontlab.com/news/color-font-format-proposals/) щоб розширити OpenType для підтримки повнокольорових шрифтів OpenType, і зрештою було прийнято та включено до офіційної специфікації OpenType чотири пропозиції. Для зручності ми можемо умовно згрупувати ці чотири варіанти на векторні та растрові — але, як показано в цій [сховища GitHub](https://github.com/simoncozens/test-fonts), специфікація OpenType достатньо гнучка, щоб підтримувати файли кольорових шрифтів OpenType, які поєднують ці чотири базові технології.

* **Векторні шрифти OpenType:**
* **Microsoft**: форми гліфів описуються за допомогою різновиду багатошарових кольорових векторів ([COLR](https://docs.microsoft.com/en-us/typography/opentype/spec/colr) та [CPAL](https://docs.microsoft.com/en-us/typography/opentype/spec/cpal) таблиць).
* [**Adobe та Mozilla**](https://www.w3.org/2013/10/SVG_in_OpenType/) ([таблиця SVG](https://docs.microsoft.com/en-us/typography/opentype/spec/svg)): форми гліфів малюються за допомогою SVG, який підтримує гліфи, побудовані з векторів *і растрових зображень*. Див. також [посібник Adobe з SVG-шрифтів](https://helpx.adobe.com/fonts/user-guide.html/fonts/using/ot-svg-color-fonts.ug.html).
* **Растрові шрифти OpenType:**
* **Google**: гліфи представлені кольоровими PNG-зображеннями, вбудованими в шрифт ([CBDT](https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt) та [CBLC](https://docs.microsoft.com/en-us/typography/opentype/spec/cblc) таблиць).
* **Apple**: гліфи також представлені кольоровими зображеннями, вбудованими в шрифт. Окрім PNG, механізм Apple ([таблиця sbix](https://docs.microsoft.com/en-us/typography/opentype/spec/colr)) також підтримує JPEG і TIFF.

Унаслідок цього операційні системи та прикладне програмне забезпечення, що підтримують кольорові шрифти OpenType, мають працювати в сучасному змішаному технологічному середовищі. Крім того, слід пам’ятати, що окремі кольорові шрифти OpenType — і *версії* одного й того самого шрифту — будуть:

* мати різне охоплення повного набору [символів емодзі Unicode](https://unicode.org/emoji/charts/emoji-list.html)— тобто скільки символів емодзі шрифт забезпечує гліфами;
* використовувати різні дизайни гліфів для представлення окремих символів емодзі;
* відрізнятися функціями, які вони надають для підтримки більш просунутих використань стандартів Unicode, таких як [які можна використовувати для створення](https://unicode.org/reports/tr51/#Emoji_Modifiers_Table), та іншими можливостями обробки тексту емодзі, описаними в [Unicode Technical Standard #51: Unicode Emoji](https://unicode.org/reports/tr51/).

#### Гул навколо HarfBuzz

Ми натякали на потребу в *рушій формування тексту*: програмному забезпеченні, яке бере вхідний Unicode-текст, записаний за допомогою певної комбінації письма й мови, і, використовуючи призначений шрифт, формує цей текст у послідовність гліфів разом із даними позиціювання, які можна використати для набору вихідного тексту.

[HarfBuzz](https://harfbuzz.github.io/) є одним із таких рушіїв формування тексту: це [бібліотека з відкритим вихідним кодом](https://github.com/harfbuzz/harfbuzz) і результат більш ніж десятирічних досліджень і розробок — і досі активно розвивається та впроваджується як частина багатьох програмних продуктів. Сам HarfBuzz не виконує «набір», але надає «послуги формування тексту» програмам, які вирішують його інтегрувати, зокрема XeTeX, LuaHBTeX, [Adobe PhotoShop та Adobe InDesign](https://en.wikipedia.org/wiki/HarfBuzz).

Інтегрувавши HarfBuzz, рушії TeX можуть скористатися його розширеними можливостями формування тексту, щоб забезпечити дуже складний багатомовний набір, особливо для складних писемностей, таких як арабська, іврит, деванагарі та багато інших. Також зауважте, що HarfBuzz використовується для обробки та формування текстових символів емодзі Unicode, що ми докладніше розглянемо.

Наведена нижче схема підсумовує роль, яку відіграє HarfBuzz, коли його інтегровано з програмним забезпеченням, таким як XeTeX або LuaHBTeX, під час набору тексту складною писемністю, наприклад арабською:

![Огляд формування арабського тексту за допомогою HarfBuzz](/files/957125daea7fef55989a1b52fdb426177cafd882)

**Досліджуємо HarfBuzz**

Усі, хто хоче дізнатися більше про HarfBuzz і послуги формування OpenType, які він надає XeTeX і LuaHBTeX, можуть [завантажити бінарний дистрибутив HarfBuzz](https://github.com/harfbuzz/harfbuzz/releases) який містить бібліотеку HarfBuzz (для програмістів) та утиліти командного рядка `hb-view` та `hb-shape`.

**Приклад: як використовувати hb-view**

Створіть новий файл у вашому улюбленому текстовому редакторі з підтримкою UTF-8 і скопіюйте/вставте такі шість символів емодзі 👋👋🏻👋🏼👋🏽👋🏾👋🏿 у цей текстовий файл, а потім збережіть його у форматі UTF-8 у файл, наприклад, `emoji.txt`.

Зверніть увагу, що ваш текстовий редактор може показувати (резервні) чорно-білі версії емодзі, оскільки він не здатний (або не запрограмований) відтворювати кольорові гліфи. Після збереження цих 6 емодзі файл `emoji.txt` має містити дані UTF-8 для такої послідовності символів емодзі Unicode — ми розділили модифікатори емодзі комами лише для *зручності читання*:

* `1F44B` щоб отримати 👋
* `1F44B`, `1F3FB` щоб отримати 👋🏻
* `1F44B`, `1F3FC` щоб отримати 👋🏼
* `1F44B`, `1F3FD` щоб отримати 👋🏽
* `1F44B`, `1F3FE` щоб отримати 👋🏾
* `1F44B`, `1F3FF` щоб отримати 👋🏿

Загалом має бути **11** символів Unicode, кожен із яких генерує 4 байти даних UTF-8, тож отриманий `emoji.txt` файл має мати розмір 44 байти, без урахування будь-яких маркерів кінця рядка, використаних у кінці рядка, що містить емодзі.

Функція `hb-view` утиліта може використати файл `emoji.txt`, разом із відповідним кольоровим шрифтом OpenType на ваш вибір, наприклад `NotoColorEmoji.ttf`, щоб згенерувати SVG-файл сформованого виводу HarfBuzz. Наведений нижче приклад командного рядка, який має бути **введений в один рядок** у вашому терміналі, згенерує SVG-файл `emoji.svg`:

```latex
hb-view --font-size=20 --output-file="emoji.svg"
--output-format=svg --text-file=emoji.txt
--font-file=NotoColorEmoji.ttf
```

У разі успішного виконання файл `emoji.svg`, згенерований за допомогою `hb-view`, можна відкрити в Inkscape, і він має виглядати приблизно так:

![Hbvieemoji.png](/files/311363e5ad2d549748a34b76b76cc7daf5e69804)

`hb-view` можна використовувати для дослідження формування HarfBuzz для будь-якого придатного файла Unicode-тексту та шрифту OpenType — це, звісно, не обмежується використанням емодзі! Введіть

```latex
hb-view --help-all
```

щоб переглянути велику кількість параметрів командного рядка для цієї потужної та зручної утиліти. Успішного формування!

## Формування тексту та рушії TeX

Тут ми розглянемо можливості формування тексту в XeTeX і в родині рушіїв TeX на основі LuaTeX.

### XeTeX

XeTeX було розроблено на початку 2000-х років, і він започаткував кілька інновацій у наборі на основі TeX, найпомітніше *вбудовану* підтримку:

* читання Unicode-тексту у форматі UTF-8;
* використання шрифтів OpenType;
* формування тексту для багатомовного набору;
* математичний набір на основі OpenType.

Здатність XeTeX легко й зручно набирати мови зі складною писемністю зумовлена його вбудованими можливостями формування тексту — спочатку на основі вже застарілого [ICU LayoutEngine](http://userguide.icu-project.org/layoutengine). Завдяки роботі Khaled Hosny XeTeX перейшов на використання HarfBuzz для формування тексту, як зазначено в оголошенні від [березня 2013 року](https://tug.org/pipermail/xetex/2013-March/024118.html). Для тих, хто хоче набирати багатомовний текст, XeTeX зазвичай називають рушієм TeX на вибір — але тепер є ще один варіант, LuaHBTeX, який ми розглянемо.

### LuaTeX і LuaHBTeX

Розробка LuaTeX почалася приблизно у 2005 році, але йшла за дизайнерською філософією, зовсім іншою, ніж у XeTeX, який вбудовував нові функції *безпосередньо в* програмне забезпечення XeTeX. На відміну від XeTeX, розробники LuaTeX вирішили «...надати мінімальний набір інструментів і жодних рішень». (див. [Reference Manual for LuaTeX](https://www.pragma-ade.com/general/manuals/luatex.pdf)). Натомість, замість надання набору додаткових функцій *вбудованих у* рушії LuaTeX, внутрішні механізми рушіїв LuaTeX відкриті, щоб розробники й досвідчені користувачі могли використовувати вбудовану мову сценаріїв Lua для створення власних рішень.

Наприклад, на відміну від XeTeX, рушій LuaTeX не може *безпосереднього* використовувати шрифти OpenType; натомість шрифти OpenType потрібно завантажувати й «підготувати до використання» через функції завантаження шрифтів, написані кодом Lua. Такі функції завантаження шрифтів називаються *callback* функціями: кодом Lua, який LuaTeX викликатиме («виконуватиме»), коли надходить запит на завантаження шрифту.

Крім того, рушій LuaTeX не надає жодних *вбудовану* можливостей формування тексту — їх теж має надавати зовнішній код, до якого рушій LuaTeX може звертатися за послугами формування тексту. І знову це контрастує з рушієм XeTeX, який інтегрував можливості формування тексту в основне програмне забезпечення.

#### luaotfload: необхідний для використання шрифтів OpenType в LuaTeX/LuaHBTeX

Механізм callback у LuaTeX для завантаження шрифтів забезпечує велику гнучкість, хоча й ціною додаткового програмування. На щастя для користувачів LuaLaTeX, спільнота TeX розробила пакет під назвою `luaotfload`, який є частиною [щорічного випуску TeX Live](https://www.tug.org/texlive/) і, звісно, доступний користувачам Overleaf.

`luaotfload` є [доступний на CTAN](https://ctan.org/pkg/luaotfload?lang=en) і має [репозиторій розробки на GitHub](https://github.com/latex3/luaotfload) де ви можете стежити за останніми розробками та [новими випусками](https://github.com/latex3/luaotfload/releases).

`luaotfload` можна завантажити безпосередньо в преамбулу документа LaTeX через

```latex
\usepackage{luaotfload}
```

Зверніть увагу, що `luaotfload` це назва LaTeX *accents*, тобто має ім’я файла `luaotfload.sty`. `luaotfload` Якщо б ви хотіли використовувати

```latex
\input luaotfload.sty
```

у вашому документі plain TeX.

Зазвичай користувачам LuaLaTeX — тобто тим, хто набирає LaTeX за допомогою LuaTeX/LuaHBTeX, — не потрібно безпосередньо працювати з `luaotfload` тому що [`fontspec` accents](https://ctan.org/pkg/fontspec) завантажить `luaotfload` пакет за вас, беручи на себе багато низькорівневих деталей через команди користувацького рівня, надані `fontspec` пакет.

### LuaHBTeX: нові параметри формування тексту

`luaotfload` є зрілою та потужною бібліотекою Lua, яка забезпечує обробку шрифтів OpenType в LuaTeX — разом із наданням послуг формування тексту для різних мов і писемностей. Спочатку функції формування тексту `luaotfload` було реалізовано чистим кодом Lua, але випуск TeX Live 2020 приніс ще один основний варіант формування тексту — новий рушій на основі LuaTeX під назвою LuaHBTeX.

«HB» у LuaHBTeX означає HarfBuzz — по суті, LuaHBTeX є оригінальним рушієм LuaTeX *плюс* з інтегрованим рушієм формування тексту HarfBuzz. Відповідно до дизайнерської філософії LuaTeX, наявність HarfBuzz не *автоматично* гарантує, що текст буде сформовано LuaHBTeX: HarfBuzz — це ще один інструмент, який можна використовувати для створення рішень формування тексту.

Інтеграція HarfBuzz у LuaHBTeX [програмується через код Lua](#introduction-to-the-luahbtex-harfbuzz-api), що дало змогу `luaotfload`розробникам додати рішення формування тексту на основі HarfBuzz. Відповідно, [починаючи з версії 3.1, випущеної 5 листопада 2019 року](https://github.com/latex3/luaotfload/releases/tag/v3.1), `luaotfload` було вдосконалено, щоб скористатися перевагами HarfBuzz, — завдяки чому можливості формування тексту HarfBuzz стали легко доступними для звичайного користувача.

Читачі, яких цікавлять технічні деталі інтеграції HarfBuzz з LuaTeX, можуть прочитати цю [статтю Khaled Hosny](https://www.tug.org/TUGboat/tb40-1/tb124hosny-harfbuzz.pdf).

### luaotfload: два варіанти формування тексту (коли використовувати HarfBuzz?)

Користувачі LuaLaTeX тепер мають два варіанти формування тексту:

* `luaotfload`оригінальну (вузлову) реалізацію формування тексту, написану виключно на Lua;
* `luaotfload`формування на основі HarfBuzz — доступне через код Lua, який викликає функції формування тексту HarfBuzz.

`luaotfload` надає доступ до цих двох систем формування через свій параметр «`mode`» — хоча більшість користувачів використовуватимуть еквівалентну `fontspec` “`Renderer`» опцію, а не безпосередньо низькорівневі функції `luaotfload`.

Кожне з `luaotfload`рішень формування тексту має свої сильні сторони та (поточні) слабкі місця, але яке з них слід використовувати і коли? Ось кілька моментів, які слід врахувати:

* `luaotfload`рідна вузлова обробка може бути вимогливою до пам’яті, особливо для великих шрифтів OpenType CJK. Використання HarfBuzz для формування тексту CJK може дати приріст швидкості та зменшення використання пам’яті.
* Використовуйте HarfBuzz для складних писемностей, оскільки він «...значно покращує відтворення індійських та арабських писемностей і настійно рекомендований для таких писемностей». (див. `luaotfload` посібник).
* Інтеграція HarfBuzz у `luaotfload` ще відносно нова і проходить подальший розвиток. На момент написання (липень 2021 року) бажано використовувати вбудоване формування luaotfload (встановлюючи `mode=node`) для основних шрифтів документа, особливо якщо документ використовує латинку. Див. цю [проблему на GitHub](https://github.com/latex3/luaotfload/issues/175#issue-801120377), де підсумовано проблеми та обговорення. Якщо хочете поекспериментувати, ви можете використати `luaotfload` для завантаження файла шрифту та створення двох шрифтів LaTeX: один використовує формування на основі HarfBuzz, а інший — формування на основі Lua. Overleaf створив [зразковий проєкт](#sample-project-arabic-shaping), який це демонструє.
* Не використовуйте HarfBuzz для роботи з математичними шрифтами. Як обговорювали розробники на tex.stackexchange, HarfBuzz [не призначений для роботи зі шрифтами для математичного набору](https://tex.stackexchange.com/questions/544881/does-luahbtex-with-harfbuzz-renderer-completely-supports-math-formating) тому не використовуйте його для цієї мети.

**Зразковий проєкт: формування арабського тексту**

Ось проєкт Overleaf, який використовує кілька високоякісних арабських шрифтів, щоб порівняти `luaotfload`вузлові служби формування тексту `mode=node`) з тими, що надає HarfBuzz (`mode=harf`):

* <https://www.overleaf.com/latex/examples/complex-script-shaping-using-luaotfload-and-harfbuzz/gfssprnhfddn>

Цей проєкт містить вивід, показаний на наведеному нижче зображенні:

![Набір арабського тексту](/files/4dd04f6005681721bfc359795848ac7703052ae2)

### Вибір «Renderer» у fontspec

Як зазначено в її [документації](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), `fontspec` «...дозволяє користувачам XeTeX або LuaTeX завантажувати шрифти OpenType в документ LaTeX». Якщо ви використовуєте рушії LuaTeX або LuaHBTeX, `fontspec` завантажить `luaotfload` бібліотеку за вас і, крім того, надасть набір зручних команд користувацького рівня, які зменшують потребу працювати з `luaotfload`низькорівневою функціональністю.

То як же вибрати між формуванням HarfBuzz і вбудованим формуванням, яке надає `luaotfload`? Відповідь міститься у чудовому [`fontspec` документації](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), а саме в Частині VI: функції шрифтів лише для LuaTeX. `fontspec` надає параметр під назвою `Renderer` який можна встановити, коли шрифт визначається через `fontspec`. `Renderer` керує низькорівневою обробкою шрифту. Два цікаві варіанти:

* `Renderer = Node`: режим за замовчуванням для набору шрифтів OpenType — він використовує `luaotfload`функції формування тексту, реалізовані виключно на Lua.
* `Renderer = Harfbuzz`: цей «режим» визначає/завантажує шрифт для використання з рушієм формування тексту HarfBuzz. `luaotfload` використовує API LuaHBTeX для виклику функцій HarfBuzz.

Докладніше див. у [`fontspec` документації](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf).

## рушії TeX, HarfBuzz і кольорові емодзі

Хоча XeTeX і LuaHBTeX обидва інтегрують HarfBuzz, вони забезпечують різний рівень підтримки деяких із більш просунутих функцій HarfBuzz — насамперед завантаження та використання кольорових шрифтів OpenType.

### XeTeX і кольорові шрифти OpenType

Як зазначалося, існують дві категорії кольорових шрифтів OpenType залежно від формату даних, що використовується для зберігання гліфів шрифту: векторні та растрові.

#### XeTeX і растрові кольорові шрифти OpenType

XeTeX не може завантажувати растрові OpenType-кольорові шрифти — такі як Google [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/) постачається з TeX Live 2020. Наприклад, якщо ви спробуєте завантажити Noto Color Emoji (NotoColorEmoji.ttf), XeLaTeX завершиться з потенційно оманливою помилкою, яка стверджує, що Noto Color Emoji «не можна знайти». Наведений нижче код LaTeX, набраний за допомогою XeLaTeX, *не працює*:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{NotoColorEmoji.ttf}
\newcommand{\smiley}{{\emojifont\char"1F600}}
\smiley
\end{document}
```

[Відкрийте цей код XeLaTeX в Overleaf (він ***не*** працює).](https://www.overleaf.com/docs?engine=xelatex\&snip_name=XeTeX+failure\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BNotoColorEmoji.ttf%7D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0A%5Csmiley%0A%5Cend%7Bdocument%7D)

Він завершується помилкою:

```
! Помилка пакета fontspec: шрифт "NotoColorEmoji" не знайдено.
```

Аналогічно, простий приклад Plain TeX, оброблений XeTeX, також завершується помилкою

```latex
\font\emojifont="[NotoColorEmoji.ttf]" at 12pt
\emojifont \char"1F600
\bye
```

[Відкрийте цей приклад Plain TeX (XeTeX) в Overleaf (він ***не*** працює).](https://www.overleaf.com/docs?engine=latex_dvipdf\&snip_name\[]=main.tex\&snip\[]=%25%5Ctitle%7Bdummy+title%7D%0A%5Cfont%5Cemojifont%3D%22%5BNotoColorEmoji.ttf%5D%22+at+12pt%0A%5Cemojifont+%5Cchar%221F600%0A%5Cbye\&snip_name\[]=readme\&snip\[]=This+project+uses+a+latexmkrc+file+to+run+xetex+not+xelatex\&snip_name\[]=latexmkrc\&snip\[]=%24latex+%3D+%27xetex%25O+%25S%27%3B+%23+to+use+the+xetex+engine\&main_document=main.tex)

Приклад Plain TeX повідомляє схоже, але інше, повідомлення про помилку:

```
! Шрифт \emojifont=[NotoColorEmoji.ttf] at 12.0pt не можна завантажити: файл Metric (TFM) fil
e або встановлений шрифт не знайдено.
l.1 \font\emojifont="[NotoColorEmoji.ttf]" at 12pt

Я не зміг(ла) прочитати дані про розмір цього шрифту,
тому я проігнорую вказівку шрифту.
[Чарівники можуть виправляти файли TFM за допомогою TFtoPL/PLtoTF.]
Можна спробувати вказати інший параметр шрифту;
наприклад, введіть `I\font<same font id>=<substitute font name>'.
```

**Приклад Plain LuaHBTeX**

Для порівняння, ось мінімальний приклад Plain TeX, скомпільований за допомогою LuaHBTeX

```latex
\input luaotfload.sty
\font\emojifont=NotoColorEmoji.ttf:mode=harf at 12pt
\emojifont \Uchar"1F600
\bye
```

[Відкрийте цей приклад Plain TeX (LuaHBTeX) в Overleaf (він успішно компілюється).](https://www.overleaf.com/docs?engine=latex_dvipdf\&snip_name\[]=main.tex\&snip\[]=%25%5Ctitle%7BPlain+TeX+with+LuaHBTeX%7D%0A%5Cinput+luaotfload.sty%0A%5Cfont%5Cemojifont%3DNotoColorEmoji.ttf%3Amode%3Dharf+at+12pt%0A%5Cemojifont+%5CUchar%221F600%0A%5Cbye\&snip_name\[]=readme\&snip\[]=This+project+uses+a+latexmkrc+file+to+run+luahbtex+not+lualatex\&snip_name\[]=latexmkrc\&snip\[]=%24latex+%3D+%27luahbtex+%25O+%25S%27%3B+%23+to+use+the+luahbtex+engine\&main_document=main.tex)

#### Справжня причина збою XeTeX

Повідомлення про помилки, які видає XeTeX, частково приховують справжню причину проблеми: OpenType-кольорові шрифти, особливо растрові варіанти, *не* підтримуються XeTeX. Насправді XeTeX (Kpathsea) може *знайти* шрифт Noto Color Emoji, але XeTeX не може повністю *завантажити* цей шрифт і не може ініціалізувати внутрішні таблиці даних шрифту, необхідні для використання цього шрифту для набору тексту. Внутрішньо XeTeX *починається* процес завантаження шрифту та перевіряє його на «масштабованість» (використовуючи «визначення» FreeType для «масштабованості»), але ця перевірка не проходить, і XeTeX видає стандартне, хоч і, мабуть, оманливе, повідомлення про помилку рушія TeX.

**Технічна примітка**

Обробку NotoColorEmoji.ttf у XeTeX було досліджено шляхом компіляції налагоджувальної версії виконуваного файла XeTeX. Для встановлення точки зупину у функції XeTeX було використано IDE Eclipse `creatFontFromFile(filename, index, pointsize)`а потім покроково пройти код, щоб спостерігати подальшу обробку.

#### XeTeX і векторні OpenType-кольорові шрифти

XeTeX може *завантажити* векторні OpenType-кольорові шрифти, але не створюватиме кольорові емодзі у результуючому PDF — якщо XeTeX взагалі його створить. На відміну від LuaTeX, LuaHBTeX і pdfTeX, XeTeX не *безпосереднього* виводить набрані документи у форматі PDF. Натомість XeTeX виводить проміжний `.xdv` (е**x**розширений **dv**i) формат файлу, який перетворюється на PDF за допомогою утиліти під назвою `xdvipdfmx`. На момент написання, `xdvipdfmx` не може вбудувати відповідні дані кольорових гліфів емодзі у PDF, тож у кращому разі ви побачите монохромні емодзі — результат «запасного варіанта» — у PDF, а можливо, не побачите нічого взагалі, залежно від використаного шрифту.

Ось приклад XeLaTeX, який використовує OpenType-кольоровий шрифт [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr), доступний у TeX Live. TwemojiMozilla.ttf використовує векторний формат Microsoft COLR/CPAL для зберігання кольорових гліфів і постачається з TeX Live 2020. У цьому прикладі XeTeX здатний завантажити шрифт, згенерувати `.xdv` і файл PDF, але гліф емодзі відсутній у набраному PDF:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}
\newcommand{\smiley}{{\emojifont\char"1F600}}
Ось смайлик: \smiley
\end{document}
```

[Відкрийте цей код XeLaTeX в Overleaf (він НЕ ПРАЦЮЄ).](https://www.overleaf.com/docs?engine=xelatex\&snip_name=XeTeX+failure\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BTwemojiMozilla.ttf%7D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0AHere+is+a+smiley%3A+%5Csmiley%0A%5Cend%7Bdocument%7D)

Натомість наведений вище код працює з LuaLaTeX, якщо визначити `\emojifont` використовуючи `fontspec` параметр `[Renderer=HarfBuzz]`:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}[Renderer=HarfBuzz]
\newcommand{\smiley}{{\emojifont\char"1F600}}
Ось смайлик: \smiley
\end{document}
```

[Відкрийте цей код LuaLaTeX в Overleaf (він працює).](https://www.overleaf.com/docs?engine=lualatex\&snip_name=LuaLaTeX+emoji+example\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BTwemojiMozilla.ttf%7D%5BRenderer%3DHarfBuzz%5D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0AHere+is+a+smiley%3A+%5Csmiley%0A%5Cend%7Bdocument%7D)

### LuaHBTeX і OpenType-кольорові шрифти

Завдяки вбудованому механізму формування HarfBuzz і `luaoftload` бібліотекою, LuaHBTeX забезпечує підтримку всіх чотирьох різновидів OpenType-кольорових шрифтів. Користувачі LuaLaTeX можуть повною мірою скористатися обробкою тексту на основі Unicode, що містить символи емодзі, або просто прикрасити свої документи дуже барвистим текстом за допомогою OpenType-кольорових шрифтів.

Як зазначалося раніше, чотири варіанти OpenType-кольорових шрифтів можна класифікувати на дві групи:

* ті, що містять гліфи у растрових форматах зображень, таких як PNG;
* інші, що використовують векторні формати SVG або механізм Microsoft COLR/CPAL.

Векторні формати гліфів мають перевагу масштабованості: вони дають чітку графіку гліфів за будь-якого кегля.

**Використання кольорових шрифтів Microsoft COLR/CPAL з LuaHBTeX**

Якщо ви хочете використовувати векторний формат для своїх OpenType-кольорових шрифтів емодзі, зверніть увагу на шрифт [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr?lang=en), який базується на форматі Microsoft COLR/CPAL. TwemojiMozilla.ttf входить до складу TeX Live, але ви можете отримати найновішу версію з його [сховища GitHub](https://github.com/mozilla/twemoji-colr/releases) і завантажити її у свій проєкт Overleaf.

Ось невеликий, `fontspec`на основі, приклад із використанням `Renderer=Harfbuzz`, який набирає велику (векторну) емодзі-качку:

```latex
\documentclass{article}
\usepackage{fontspec}
\title{Duck demo}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz,SizeFeatures={Size=400}]{TwemojiMozilla.ttf}
\emojifont\Uchar"1F986
\end{document}
```

[Відкрийте цей приклад LuaLaTeX, щоб набрати векторну качку.](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+an+emoji+duck\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Ctitle%7BDuck+demo%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D400%7D%5D%7BTwemojiMozilla.ttf%7D%0A%5Cemojifont%5CUchar%221F986%0A%5Cend%7Bdocument%7D)

Ось (векторна) качка, яку створює наведений вище приклад:

![](/files/2474e88c37a1c660de791879eaf98192c69ff623)

#### Використання кольорових шрифтів OpenType на основі SVG із LuaHBTeX

На момент написання цього оновлення статті (липень 2023 року) існує небагато формальної документації щодо використання OpenType-кольорових шрифтів у форматі SVG з LuaLaTeX. Деякі [коментарі в онлайн-обговореннях](https://github.com/latex3/luaotfload/issues/96) радять використовувати `fontspec`’s `RawFeature`, як показано в псевдокоді нижче. Замініть `*назву вашого SVG-файлу шрифту тут*` на назву SVG-файлу шрифту, доступного для вашого коду LaTeX:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emoji[RawFeature={+svg},SizeFeatures={Size=20}]{your SVG font file name here}
\emoji Ваш емодзі тут...
\end{document}
```

Якщо ви опустите `fontspec` і завантажите `luaotfload` безпосередньо, вам може знадобитися оголосити та вказати шрифт у такий спосіб — наші експерименти показують, що вам потрібно опустити `mode=harf` параметр, щоб це запрацювало:

```latex
\font\emoji=[your SVG font file name here]:+svg;
```

**Кілька застережень**

Читачам, які хочуть використовувати OpenType-кольорові шрифти у форматі SVG, слід врахувати:

* OpenType-шрифти у форматі SVG, що містять велику кількість гліфів, можуть бути [обчислювально затратними для LuaLaTeX](#processing-svg-glyph-data) для обробки, що потенційно призводить до [тайм-аутів Overleaf](/latex/uk/baza-znan/038-fixing-and-preventing-compile-timeouts.md).
* Підтримка цих шрифтів у LuaLaTeX може [вважатися експериментальною](https://github.com/latex3/luaotfload/issues/96#issuecomment-530317399): результати можуть відрізнятися залежно від випуску TeX Live, який використовує ваш проєкт; отже, радимо експериментувати й діяти обережно.

**Обробка даних SVG-гліфів**

SVG дає змогу дизайнерам створювати складні та барвисті зображення, що представляють гліфи шрифту, — з урахуванням деяких обмежень SVG [описаних у специфікації OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/svg). Однак рушії TeX, включно з LuaHBTeX, не можуть безпосередньо імпортувати (використовувати) SVG-файли або дані — наприклад, SVG-дані, що використовуються для опису форм гліфів у OpenType-кольорових шрифтах у форматі SVG. SVG-дані гліфа мають бути перетворені у формат PDF, оскільки LuaHBTeX може використати їх для набору гліфа та створення фінального PDF-документа. Це перетворення SVG у PDF виконується кодом Lua всередині `luaoftload`: SVG-дані кожного гліфа витягуються з файла шрифту, зберігаються у тимчасовому `.svg` файлі та перетворюються на PDF за допомогою Inkscape через командний рядок. Витягування SVG-даних і перетворення їх у PDF створює певні накладні витрати на обробку, що може призвести до тривалого часу компіляції документа — особливо для документів, які використовують великі SVG-шрифти, що містять тисячі гліфів емодзі.

#### Растрові OpenType-кольорові шрифти

**Використання формату OpenType-кольорових шрифтів Google CBDT/CBLC з LuaHBTeX**

[Noto Color Emoji](https://fonts.google.com/noto/specimen/Noto+Color+Emoji) є OpenType-кольоровим шрифтом, що входить до складу TeX Live, тож його легко використовувати в проєкті Overleaf. Оскільки Noto Color Emoji використовує графіку у форматі PNG для представлення гліфів емодзі, ми можемо використати його для набору великого (растрового) емодзі-качки — як показано в наведеному нижче прикладі. Знову ж таки, зверніть увагу, що `fontspec` оголошення шрифту (`\emojifont`) використовує `Renderer=Harfbuzz`.

```latex
\documentclass{article}
\usepackage{fontspec}
\title{Duck demo}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz,SizeFeatures={Size=400}]{NotoColorEmoji.ttf}
\emojifont\Uchar"1F986
\end{document}
```

[Відкрийте цей приклад LuaLaTeX, щоб набрати растрову качку.](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+a+large+raster+duck\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Ctitle%7BDuck+demo%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D400%7D%5D%7BNotoColorEmoji.ttf%7D%0A%5Cemojifont%5CUchar%221F986%0A%5Cend%7Bdocument%7D)

Ось растрова качка, яку створює наведений вище приклад:

![Растрове емодзі-качка, набране LaTeX](/files/9a2aa5d4defa3492a45b7af90b2afaef26adadf0)

Якщо ви спробуєте використати `NotoColorEmoji.ttf` але пропустите `[Renderer=Harfbuzz]` з `fontspec` оголошення, LuaHBTeX завершиться помилкою й видасть повідомлення про помилку, коли спробує записати PDF-файл:

```latex
! помилка:  (file /usr/local/texlive/2020/texmf-dist/fonts/truetype/google/noto-em
oji/NotoColorEmoji.ttf) (ttf): таблицю loca не знайдено
```

Причина цієї помилки в [таблиці loca](https://docs.microsoft.com/en-us/typography/opentype/spec/loca) є [пояснена на GitHub](https://github.com/latex3/luaotfload/issues/98#issuecomment-531610153).

**Використання формату OpenType-кольорових шрифтів Apple sbix з LuaHBTeX**

Автономні тести показують, що LuaHBTeX підтримує `sbix` варіант OpenType-кольорового шрифту, але на момент написання цієї статті нам не вдалося знайти належним чином ліцензований `sbix`-варіант кольорового шрифту емодзі для демонстрації набору качки. Будь ласка, [зв’яжіться з нами](https://www.overleaf.com/contact) якщо ви знаєте такий, повідомте нам, і ми «крякво» оновимо цю статтю, щоб використати його.

## Вступ до API HarfBuzz у LuaHBTeX

![Db.gif](/files/578e0ae88e0c910a6fcfd70dfd64c73f34cef622) ![Db.gif](/files/578e0ae88e0c910a6fcfd70dfd64c73f34cef622)

Формування тексту, особливо для мов зі складним письмом, і навіть емодзі, — це за своєю природою складне завдання, тож, не дивно, HarfBuzz є складною бібліотекою, з якою може бути непросто працювати, якщо ви вже не знайомі з операціями формування тексту. У цьому завершальному розділі ми розглянемо інтеграцію HarfBuzz у LuaHBTeX і те, як отримати до неї доступ через код Lua всередині `\directlua`.

Наш приклад використовує досить простий код, щоб продемонструвати API HarfBuzz у LuaHBTeX. Він дещо штучний, не промислового рівня якості й не надто практичний, оскільки його єдина мета — познайомити з деякими основними ідеями. Ми поділили код Lua на дві `\directlua` частини: перша завантажує `luaharfbuzz` бібліотеку та створює деякі глобальні змінні, які ми використаємо в нашій другій `\directlua` частині, де ми визначаємо макрос під назвою `\codestoemoji`.

Здається доречним відтворити використання Кнутом подвійних знаків небезпечного повороту (зображення надано [цим сайтом](http://www.truetex.com/db.htm)) оскільки вміст є дещо низькорівневим і «зазиряє під капот» — хоча ми сподіваємося, що він може зацікавити більш відважного читача. Інтеграція HarfBuzz у LuaHBTeX походить із [проєкту luaharfbuzz на GitHub](https://github.com/ufyTeX/luaharfbuzz/wiki#projects-using-luaharfbuzz) де ви можете знайти [вступ до проєкту](https://github.com/ufyTeX/luaharfbuzz/wiki) разом із [переліком API luaharfbuzz](http://ufytex.github.io/luaharfbuzz/).

### Перші кроки: завантаження бібліотеки luaharfbuzz і пошук шрифту

Щоб використовувати API HarfBuzz у LuaHBTeX, спершу потрібно завантажити бібліотеку (модуль) під назвою `luaharfbuzz`, вбудовану в LuaHBTeX, і зберегти повернену таблицю в (глобальній) змінній, яку ми назвемо `hblib`:

```latex
hblib=require("luaharfbuzz")
```

Далі нам потрібно знайти відповідний OpenType-кольоровий шрифт емодзі: ми використаємо Noto Color Emoji — зауважте, що ми тут дуже ледачі й не виконуємо жодної перевірки помилок на випадок, якщо не знайдемо його! Щоб знайти його, ми скористаємося `kpse` бібліотекою (Kpathsea), яка також є частиною LuaTeX/LuaHBTeX:

```latex
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")
```

Тепер, коли ми маємо доступ до бібліотеки HarfBuzz через нашу змінну `hblib`, і шлях до відповідного шрифту (`pathtofontfile`), ми можемо почати використовувати `hblib`. `\directlua` фрагмент коду, де ми визначаємо наш макрос.

```latex
% Створити HarfBuzz face і HarfBuzz font з Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)
```

#### HarfBuzz font і HarfBuzz face: що це таке?

Скопійований [Об'єкт HarfBuzz face](https://harfbuzz.github.io/fonts-and-faces.html) представляє гарнітуру, завантажену з файла шрифту, але без встановлення конкретних параметрів (таких як розмір). [Об'єкт HarfBuzz font](https://harfbuzz.github.io/fonts-and-faces.html) представляє *конкретний екземпляр* об'єкта HarfBuzz face; отже, з одного об'єкта HarfBuzz face можна отримати різні об'єкти HarfBuzz font: для кожного HarfBuzz font його властивості, такі як розмір, можна встановлювати в різні значення. HarfBuzz face — це вищий рівень абстракції, ніж HarfBuzz font.

### Використання гліфів шрифту для створення PNG-файлів

Остання частина нашого першого `\directlua` фрагмента — це функція під назвою `writePNGglyph(hbfontobject, glyphID)` яку ми використовуємо, щоб продемонструвати, що деякі OpenType-кольорові шрифти, такі як Noto Color Emoji, використовують графіку PNG для представлення гліфів емодзі, які вони містять.

Ця функція використовує API HarfBuzz у LuaHBTeX, щоб витягти PNG-дані з гліфів і записати ці дані у `.png` файлу з назвою `Graphics<glyphID>.png`. Назва цього `.png` файла повертається для використання `\includegraphics` для вбудовування зображень PNG-гліфів у наш набраний PDF.

З `writePNGglyph(hbfontobject, glyphID)` на місці, наш перший `\directlua` фрагмент коду виглядає так:

```latex
\directlua{

% Завантажити бібліотеку luaharfbuzz з LuaHBTeX
hblib=require("luaharfbuzz")

% Знайти шрифт Noto Color Emoji на сервері Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Створити HarfBuzz face і HarfBuzz font з Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% Ця функція приймає шрифт і ідентифікатор гліфа:
% вона витягує PNG-дані гліфів і записує
% їх у файл .png

function writePNGglyph(hbfontobject, glyphID)

    % Отримати PNG-дані гліфа
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % Сформувати ім'я файла для нашого файлу .png
    local fname="Glyph"..glyphID..".png"

    % Записати файл .png і повернути ім'я файла
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % Повернути ім'я файла для використання \includegraphics
    return fname
end
}
```

### Другий фрагмент \directlua: створення макроса \codestoemoji

Мета — визначити макрос `\codestoemoji` який можна викликати з фрагментом тексту, що містить коди символів емодзі, які ми хочемо, щоб HarfBuzz сформував. Зокрема, ми використаємо `\Uchar<character code>` для представлення кожного символу емодзі; наприклад:

```latex
\codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
```

У визначенні `\codestoemoji` відбувається багато чого, що ми пояснимо нижче, але визначення має такий вигляд:

```latex
\newcommand{\codestoemoji}[1]{%
\directlua{

local str="#1"
local hbbuffer = hblib.Buffer.new()
hbbuffer:add_utf8(str)

hbbuffer:set_direction(hblib.Direction.new("ltr"))
local res = hblib.shape_full(hbfont, hbbuffer, {},{})

if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % Таблиця гліфів, hbglyphs, індексується з 1
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % Зменшити розмір імпортованих PNG-зображень
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}
```

#### Розуміння визначення макроса \codestoemoji

Функція `\codestoemoji` макрос — це переважно код Lua, що міститься всередині `\directlua`, тож якщо ви хочете дізнатися більше про *як* `\directlua` те, як це працює, ознайомтеся зі статтею Overleaf [Розуміння `\directlua`](/latex/uk/dokladni-statti/09-an-introduction-to-luatex-part-2-understanding-directlua.md). У ній пояснюється, як LuaTeX і LuaHBTeX обробляють `\directlua` коли команди TeX/LaTeX включено в код Lua, і, зокрема, необхідність використовувати `\noexpand` та `\unexpanded`.

**Робота з параметром макроса: "#1"**

Макрос починається з цих трьох рядків:

```latex
local str="#1"
local hbbuffer = hblib.Buffer.new()
hbbuffer:add_utf8(str)
```

які виконують такі завдання:

* `local str="#1"`: це створює рядок Lua з вхідних даних, переданих макросом;
* `local hbbuffer = hblib.Buffer.new()`: це використовує API HarfBuzz для створення буфера, що міститиме текст, який ми хочемо, щоб HarfBuzz сформував;
* `hbbuffer:add_utf8(str)`: це додає рядок у форматі UTF-8, створений з вхідних даних нашого макроса, до буфера HarfBuzz.

Перший рядок коду

```latex
local str="#1"
```

здається досить простим, але його робота пов'язана з чималою складністю, яку варто розглянути трохи детальніше.

Якщо розглянути третій рядок коду

```latex
hbbuffer:add_utf8(str)
```

ми бачимо, що він використовує нашу `str` змінну, щоб надати буферу HarfBuzz рядок Unicode, відформатований у UTF-8. Щоб це працювало, змінна `str` сама має містити текст Unicode, відформатований як UTF-8; тож виникає питання: *як* чи LuaHBTeX «перетворив» аргумент макроса `"#1"`, що містить `\Uchar` команди, у рядкову змінну Lua `str` що містить текст UTF-8 для HarfBuzz?

Якщо подивитися на наше заплановане використання `\codestoemoji` макроса:

```latex
\codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
```

вхідні дані, такі як `\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065...`, зовсім не схожі на послідовність символів емодзі, закодованих у UTF-8. Крім того, HarfBuzz нічого не знає про команди TeX. Якимось чином необроблені вхідні дані TeX, що складаються з `\Uchar` команд, перетворюються на символи Unicode, закодовані в UTF-8, які HarfBuzz може використовувати, але *як*?

Відповідь полягає в поведінці `\Uchar` команди: спроба викликати `\codestoemoji` за допомогою `\char` замість `\Uchar` завершиться невдачею, але *чому*?

**\Uchar: розгортання в \directlua**

Коли `\codestoemoji` макрос викликається, `\directlua` команда, що зберігається у визначенні макроса, має підготувати код Lua для надсилання до вбудованого інтерпретатора Lua у LuaHBTeX. Частиною цього процесу підготовки коду є розгортання будь-яких команд TeX/LaTeX, наявних у початковому коді Lua у визначенні макроса, разом із розгортанням будь-яких аргументів макроса, наданих користувачем. Цей процес розгортання дає список токенів, який згодом перетворюється назад у текст, утворюючи код Lua для передачі інтерпретатору Lua. Для зручності ми відтворюємо діаграму зі статті Overleaf [Розуміння `\directlua`](/latex/uk/dokladni-statti/09-an-introduction-to-luatex-part-2-understanding-directlua.md):

![Механіка \directlua](/files/0ae3d9486b3a6b1982fd13b7854cccba3ae1f62d)

Макрос `\codestoemoji` призначений для виклику за допомогою `\Uchar` команд і, [як зазначалося раніше в статті](#the-key-difference-expansion), `\Uchar` є розширюваною командою, чиє розгортання породжує символьний токен. Під час обробки `\directlua`, LuaHBTeX розгортає кожну `\Uchar<character code>` команду там, де *видаляє* кожного `\Uchar<character code>` з вхідних даних і *замінює* її відповідним значенням розгортання: символьним токеном, що представляє `<код символу>`.

На завершальному етапі обробки початковий список токенів, створений `\directlua` перетворюється *назад у текст* щоб стати кодом Lua, призначеним для інтерпретатора Lua (див. діаграму вище). Усі символьні токени, створені під час розгортання `\Uchar` також *перетворюються назад у текст*: це перетворення символьних токенів у текст створює UTF-8-представлення початкових `<код символу>` значень.

У нашому прикладі на момент, коли код Lua згенеровано й він готовий для інтерпретатора Lua, вхідні дані макроса для "#1" уже перетворено на послідовність тексту UTF-8: `str` змінна тепер є текстовим рядком UTF-8, який можна безпечно додати до буфера HarfBuzz.

**Чому \char не працює?**

Пряма відповідь: тому що `\char` є *не* розширювана команда. На відміну від `\Uchar` команд, `\char` команди *не видаляються* з вхідних даних під час `\directlua`початкової обробки для створення списку токенів, вони «проходять крізь» і включаються до списку токенів, що створюється `\directlua`. Наприклад, якщо аргумент до `\codestoemoji` містив `\char"1F3F4` LuaHBTeX перетворив би це на послідовність токенів і зберіг би їх як частину загального списку токенів, що генерується.

На наступному етапі обробки, під час перетворення токенів назад у текст, отриманий код Lua містив би *буквальний рядок* `\char"1F3F4` у тексті, що використовується для визначення нашої змінної `str`. Коли вміст `str` додається до буфера HarfBuzz, він не міститиме послідовності, закодованої в UTF-8, що представляє символ емодзі "1F3F4, натомість міститиме буквальний рядок `\char"1F3F4`, який HarfBuzz спробує сформувати і, для наших цілей, не дасть гліф емодзі. До речі, рядок `\char"1F3F4` також спричинив би синтаксичні помилки Lua, якщо тільки його не створити як «довгий рядок у квадратних дужках» — див. [Що таке escape-послідовності Lua](/latex/uk/dokladni-statti/09-an-introduction-to-luatex-part-2-understanding-directlua.md#what-are-e2809clua-escape-sequencese2809d3f) для довідки щодо цієї проблеми.

Якщо ми спробуємо використати `\codestoemoji` на `\char` команду, ось так:

```latex
\codestoemoji{\char"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
```

LuaHBTeX завершиться помилкою і повідомить про синтаксичну помилку приблизно так:

```latex
[\directlua]:1: invalid escape sequence near '"\c'.
\codestoemoji ...ing \includegraphics }.}]]) end }

l.75 ...r"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}

Інтерпретатор Lua зіткнувся з проблемою, тож
решту цього фрагмента Lua буде проігноровано.
```

#### Виклик функції формування HarfBuzz

**Налаштування параметрів буфера**

HarfBuzz іноді потребує додаткової інформації про текст, який йому пропонують сформувати. Ви можете надати цю інформацію, налаштувавши свій `<змінна буфера>` за допомогою *методи буфера*, такі як:

* `<змінна буфера>:set_direction(*напрям HarfBuzz*)`;
* `<змінна буфера>:set_language(*мова HarfBuzz*)`;
* `<змінна буфера>:set_script(*скрипт HarfBuzz*)`.

Наприклад, нам потрібно повідомити HarfBuzz, що напрямок нашого тексту з емодзі буде зліва направо. Для цього ми використовуємо `set_direction()` метод у нашому `<змінна буфера>` (який називається `hbbuffer`) записуючи:

```latex
hbbuffer:set_direction(hblib.Direction.new("ltr"))
```

де `hblib.Direction.new("ltr")` створює «об’єкт напрямку», придатний для передавання до рушія HarfBuzz через Lua.

**Виконати формування**

Після того як буфер належним чином ініціалізовано, ми можемо попросити HarfBuzz виконати власне формування за допомогою функції `shape_full()`. У нашому прикладі ми пишемо:

```latex
local res = hblib.shape_full(hbfont, hbbuffer, {},{})
```

3-й і 4-й параметри `shape_full()` функції мають бути таблицями Lua — ми використали порожні таблиці «`{}`» для обох параметрів. Загальна форма `shape_full()` така:

```latex
shape_full(шрифт HarfBuzz, буфер HarfBuzz, {можливості шрифту}, {"shaper"}
```

* **`{"shaper"}`**: Зазвичай не потрібно встановлювати, але варіанти такі `{"ot"}` або `{"graphite2"}`. Більше інформації про поняття «shaper» можна знайти в [документації HarfBuzz](https://harfbuzz.github.io/shaping-and-shape-plans.html)—зверніть увагу, що тут описано низькорівневий C API, а не Lua-оснований `luaharfbuzz` зв’язку (реалізації).
* **`{можливості шрифту}`**: Це таблиця, що перелічує [функції OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist)—підтримувані шрифтом, — які ви хочете, щоб HarfBuzz застосував під час формування.

Будь-яку можливість шрифту, яку ви хочете використати, потрібно створити за допомогою `luaharfbuzz` функції бібліотеки

```latex
library_instance.Feature.new(feature_string)
```

де

* `library_instance` це ваша `luaharfbuzz` змінна екземпляра бібліотеки (`hblib` у нашому прикладі);
* `feature_string` використовує [синтаксис для визначення можливостей](https://github.com/ufytex/luaharfbuzz/wiki/Feature-Strings). Прикладами цього є `+smcp` для вмикання малих капітелей або `-kern` для вимкнення кернінгу.

Наприклад:

```latex
local dosmcp = hblib.Feature.new("+smcp")
local nokern = hblib.Feature.new("-kern")
% Використовуйте можливості шрифту ось так
local res = hblib.shape_full(hbfont, hbbuffer, {dosmcp,nokern},{})
```

#### Доступ до результату: отримання гліфів

І нарешті, якщо операція формування успішна, сформовані гліфи повертаються у змінній буфера `hbbuffer` яку ми створили раніше в коді.

Ми отримуємо доступ до гліфів через метод буфера `get_glyphs()` і використовуємо цикл, щоб отримати кожен окремий гліф. Зверніть увагу, що таблиця Lua, яка містить гліфи, `hbglyphs` у нашому прикладі індексується, починаючи з 1, а не з 0.

Для кожного гліфа *ідентифікатор гліфа* (що заплутано називається `кодпойнт`), а шрифт HarfBuzz (`hbfont`), передається до `writePNGglyph()` функції, яка створює PNG-файл, використовуючи растрове зображення цього гліфа, подане шрифтом.

`writePNGglyph()` записує PNG-файл і повертає ім’я PNG-файлу, яке використовується для імпорту (масштабованого) PNG-файлу в наш документ LaTeX через `\includegraphics[scale=0.75]{<fname>}`. Зверніть увагу, як ми можемо використовувати `\includegraphics` безпосередньо в коді Lua.

```latex
if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % Таблиця гліфів, hbglyphs, індексується з 1
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % Зменшити розмір імпортованих PNG-зображень
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
```

### Повний код, який ви можете відкрити в Overleaf

```latex
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\directlua{

% Завантажити бібліотеку luaharfbuzz з LuaHBTeX
hblib=require("luaharfbuzz")

% Знайдіть шрифт Noto Color Emoji на сервері Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Створити HarfBuzz face і HarfBuzz font з Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% Ця функція приймає шрифт і ідентифікатор гліфа:
% він витягує PNG-дані гліфів і записує
% їх у файл .png

function writePNGglyph(hbfontobject, glyphID)

    % Отримати PNG-дані гліфа
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % Сформувати ім'я файла для нашого файлу .png
    local fname="Glyph"..glyphID..".png"

    % Записати файл .png і повернути ім'я файла
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % Повернути ім'я файла для використання \includegraphics
    return fname
end
}

\newcommand{\codestoemoji}[1]{%
\directlua{

local str="#1"
local hbbuffer = hblib.Buffer.new()
hbbuffer:add_utf8(str)

hbbuffer:set_direction(hblib.Direction.new("ltr"))
local res = hblib.shape_full(hbfont, hbbuffer, {},{})

if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % Таблиця гліфів, hbglyphs, індексується від 1.
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % Зменшити розмір імпортованих PNG-зображень
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}

Качка: \codestoemoji{\Uchar"1F986}

Прапор: \codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
\end{document}
```

[Відкрийте цей приклад API luaharfbuzz в Overleaf.](/latex/uk/dokladni-statti/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md)

Цей приклад дає такий результат:

![Harfbuzzexample.png](/files/8025d5b2bc8210837f31e545fcd06768b28405a7)

## Додатковий розділ: Весела математика з емодзі

На завершення в легкому дусі, один із команди Overleaf використав [`емодзі` пакет LaTeX](https://ctan.org/pkg/emoji?lang=en) щоб створити веселий приклад:

```latex
\documentclass{article}
\usepackage{emoji}
\usepackage{unicode-math,fontspec}
\setmainfont{STIX}
\setmathfont{STIX Two Math}
\begin{document}
\newcommand{\emomath}[1]{\text{\emoji{#1}}}
\[
e^{\emomath{droplet} \ln\emomath{smile}}=\emomath{sweat-smile}
\]
\[
e^{\emomath{eye}\emomath{pie}}=-1
\]
\end{document}
```

[Відкрийте цей веселий приклад в Overleaf](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Fun+with+emoji+math\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bemoji%7D%0A%5Cusepackage%7Bunicode-math%2Cfontspec%7D%0A%5Csetmainfont%7BSTIX%7D%0A%5Csetmathfont%7BSTIX+Two+Math%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewcommand%7B%5Cemomath%7D%5B1%5D%7B%5Ctext%7B%5Cemoji%7B%231%7D%7D%7D%0A%5C%5B%0Ae%5E%7B%5Cemomath%7Bdroplet%7D+%5Cln%5Cemomath%7Bsmile%7D%7D%3D%5Cemomath%7Bsweat-smile%7D%0A%5C%5D%0A%5C%5B%0Ae%5E%7B%5Cemomath%7Beye%7D%5Cemomath%7Bpie%7D%7D%3D-1%0A%5C%5D%0A%5Cend%7Bdocument%7D)

Цей приклад дає такий результат:

![Emojimath2.png](/files/b5dc581a64e1111554566835ef3010bd1a150e9b)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/uk/dokladni-statti/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
