> 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/pl/artykuly-szczegolowe/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md).

# Przegląd technologii wspierających użycie kolorowych czcionek emoji w LaTeX-u

## Wstęp

Niniejszy artykuł przedstawia przegląd różnych [tematów wprowadzających](#which-topics-do-we-cover) związanych z używaniem kolorowych czcionek OpenType do składu kolorowych emoji w LaTeX-u. Staraliśmy się przedstawić szeroki zakres materiałów, odpowiadający zróżnicowanym zainteresowaniom i poziomowi wiedzy. Aby artykuł pozostał czytelny, nasze omówienie niektórych tematów pomija wiele szczegółów technicznych, ale mamy nadzieję, że materiału jest wystarczająco dużo, by ukierunkować Twoje dalsze badania nad składem kolorowych emoji w LaTeX-u.

**Aktualizacja (lipiec 2023)**: Ten artykuł został po raz pierwszy opublikowany w sierpniu 2021 roku i zaktualizowany w lipcu 2023 roku, aby uzupełnić sekcję o [Korzystanie z kolorowych czcionek OpenType opartych na SVG z LuaHBTeX](#using-svg-based-opentype-color-fonts-with-luahbtex).

### Jakie tematy omawiamy?

Niniejszy artykuł obejmuje następujące ogólne tematy:

* Unicode: standard, który koduje emoji jako znaki i określa ich oczekiwane zachowanie w aplikacjach do przetwarzania tekstu i składu tekstu.
* Kolorowe czcionki OpenType: wyspecjalizowane czcionki, które zapewniają barwne reprezentacje znaków emoji wyświetlanych w Twoim dokumencie LaTeX.
* Kształtowanie tekstu: wprowadzenie do kluczowego komponentu składu języków o złożonym piśmie i emoji.
* HarfBuzz: komponent LuaHBTeX, który umożliwia zaawansowany skład wielojęzyczny i użycie kolorowych czcionek OpenType do składu emoji w LaTeX-u.
* Różne silniki TeX: omówienie ich obsługi kolorowych czcionek OpenType i wybór silnika TeX do użycia.
* API HarfBuzz w LuaHBTeX: wprowadzenie do „magii” stojącej za [kształtowaniem tekstu](#the-concept-of-text-shaping) w LuaHBTeX.

### Trzy sposoby składu kolorowych emoji

Kolorowe emoji można składać w LaTeX-u za pomocą trzech głównych metod:

1. Używanie standardowych narzędzi graficznych LaTeX, takich jak TikZ, MetaPost lub Asymptote, do rysowania emoji.
2. Wstawianie emoji przy użyciu wcześniej przygotowanych grafik emoji przechowywanych w plikach zewnętrznych.
3. Traktowanie emoji jako tekstu zakodowanego w Unicode i używanie [kształtowaniem tekstu](#the-concept-of-text-shaping) z [kolorowych czcionek OpenType](#opentype-color-fonts) do ich składu.

Praktyczne możliwości wstawiania kolorowych emoji do dokumentu LaTeX zależą od silnika TeX używanego do kompilacji tego dokumentu, tzn. od tego, czy używasz:

* pdfLaTeX: silnik pdfTeX + LaTeX;
* XeLaTeX: silnik XeTeX + LaTeX;
* LuaLaTeX: silnik LuaHBTeX (od TeX Live 2020) + LaTeX.

Wszystkie trzy z tych silników TeX mogą używać narzędzi lub pakietów LaTeX do rysowania emoji albo korzystać z `\includegraphics{...}` do wstawiania emoji przechowywanych w zewnętrznych plikach graficznych. Rysowanie lub importowanie grafiki to idealne techniki składu emoji, gdy potrzebujesz rozwiązania niezależnego od silnika TeX używanego do kompilacji dokumentu LaTeX.

Jeśli jednak Twój przepływ pracy daje elastyczność wyboru konkretnego silnika TeX i wolisz używać kolorowych czcionek OpenType oraz przetwarzania tekstu opartego na Unicode, potrzebna jest najnowsza wersja LuaTeX, zwana LuaHBTeX. Począwszy od TeX Live 2020, LuaHBTeX jest używany do kompilacji dokumentów LaTeX opartych na formacie LuaLaTeX.

## Tło dotyczące Unicode i znaków emoji

### Kodowania znaków

Komputery przechowują, przesyłają i przetwarzają tekst przy użyciu sekwencji wartości liczbowych (całkowitych), które reprezentują składowe *znaki*. Niezawodne przetwarzanie tekstu wymaga, aby producenci i odbiorcy tekstu uzgadniali, które wartości całkowite mają być używane do reprezentowania poszczególnych znaków w strumieniu tekstu. Innymi słowy, jakie jest *znaku* *kodowanie tego tekstu?* Kodowanie to zbiór uzgodnionych wartości całkowitych przypisanych do reprezentowania określonego zestawu znaków: każdy znak jest reprezentowany przez wartość całkowitą w używanym kodowaniu.

### Wkracza Unicode

Historycznie, w epoce 8-bitowego tekstu, używano wielu różnych kodowań znaków, co zawsze rodziło widmo *niezgodności kodowań*: producent i odbiorca tekstu błędnie zakładają różne kodowania, co skutkuje błędami przetwarzania tekstu. Każdy, kto przez kilka lat pracował z TeX/LaTeX-em, prawdopodobnie spotkał się z niezgodnościami kodowań między tekstem wejściowym a czcionkami używanymi do składu dokumentu. Jeśli czcionki dokumentu są skonfigurowane tak, aby używać kodowania innego niż tekst, prawdopodobnie skutkuje to brakującymi lub błędnymi znakami w składanym pliku PDF.

Te historyczne problemy z kodowaniem można rozwiązać za pomocą międzynarodowego standardu kodującego wszystkie znaki świata: Unicode. Standard Unicode nie jest statyczny, lecz jest okresowo aktualizowany, aby uwzględniać dodatkowe znaki i skrypty (systemy pisma) w swoim schemacie kodowania. Istnieje [formalny proces recenzji zgłaszania nowych znaków](http://www.unicode.org/pending/proposals.html) z określonym [schematem dla nowych znaków emoji](https://www.unicode.org/emoji/proposals.html).

### Ile znaków Unicode?

Unicode koduje teoretyczne maksimum 1 114 112 znaków. Każda z 1 114 112 wartości całkowitych jest nazywana *punktem kodowym*: wartością całkowitą przypisaną do identyfikacji każdego znaku. Jednak z różnych przyczyn technicznych tylko [1 112 064 punktów kodowych](https://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology) można przypisać rzeczywistym znakom: 2048 punktów kodowych jest nieprzypisywalnych i zabronionych do użycia w tekście zgodnym z Unicode.

W chwili pisania tego tekstu (pierwszej wersji tego artykułu) wersja 13 standardu Unicode przydzieliła łącznie 143 859 punktów kodowych rzeczywistym znakom, w tym [3304 znaki obecnie zakodowane jako emoji](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (zobacz stronę 2 tego dokumentu). Wzrost liczby znaków kodowanych przez Unicode jest dobrze udokumentowany w artykule [Ile jest znaków Unicode?](https://www.babelstone.co.uk/Unicode/HowMany.html) oraz w [hasle Wikipedii](https://en.wikipedia.org/wiki/Unicode#Versions).

### Płaszczyzny Unicode

Cały zbiór 1 114 112 punktów kodowych Unicode jest podzielony na 17 tak zwanych Płaszczyzn: Płaszczyznę 0 do Płaszczyzny 16, z których każda zawiera 65 536 wartości punktów kodowych, dając łącznie $$17\times2^{16} = 1,114,112$$ znaków. Płaszczyzna 0, zwana [Podstawową Płaszczyzną Wielojęzyczną](https://en.wikipedia.org/wiki/Plane_\(Unicode\)#Basic_Multilingual_Plane), koduje najczęściej używane znaki. Płaszczyzny 1–16 nazywane są [Płaszczyznami Uzupełniającymi](http://unicode.org/glossary/#supplementary_planes).

### Rozwój emoji

Nowe znaki powstają wraz ze zmieniającymi się sposobami komunikacji międzyludzkiej, a technologia telefonów komórkowych doprowadziła do powstania jednego takiego zestawu znaków: emoji, które rozwinęły się w Japonii pod koniec lat 90. Nic dziwnego, że [FAQ Unicode na temat emoji](https://unicode.org/faq/emoji_dingbats.html) zauważa

> „Słowo emoji pochodzi z japońskich [絵](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E7%B5%B5) (e ≅ obraz) + [文字](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E6%96%87) (moji ≅ zapisany znak).”

Czytelnicy zainteresowani tłem i historycznym rozwojem emoji mogą znaleźć coś ciekawego w tym [wprowadzeniu do Unicode](https://unicode.org/reports/tr51/#Introduction) lub w artykule [I second that emoji: standardy, struktury i społeczne wytwarzanie emoji](https://firstmonday.org/ojs/index.php/fm/article/view/9381).

Dopiero w 2010 roku, wraz z wydaniem [wersji 6.0 standardu Unicode](https://www.unicode.org/versions/Unicode6.0.0/), wiele emoji zostało formalnie uznanych za *znaki* samodzielne znaki. Unicode 13.0 zakodował [3304 znaki jako emoji](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (zobacz stronę 2 tego dokumentu), a Unicode 13.1 wymienia [wymienia 3521 emoji](https://unicode.org/emoji/charts/emoji-counts.html).

### Emoji żyją na wyższej płaszczyźnie

Unicode przypisał wiele znaków emoji do punktów kodowych poza Podstawową Płaszczyzną Wielojęzyczną (BMP), zakodowanych [w Płaszczyźnie 1](https://en.wikibooks.org/wiki/Unicode/Character_reference/1F000-1FFFF) z punktami kodowymi w zakresie 1F000–1FFFF — co ma ważną konsekwencję dla każdego, kto chce *skopiować i wkleić* znaki emoji do edytorów Overleaf (Edytora Kodu lub Edytora Wizualnego). Edytory tekstowe Overleaf mogą obsługiwać tylko znaki w obrębie Podstawowej Płaszczyzny Wielojęzycznej, choć mamy nadzieję, że przyszłe aktualizacje wprowadzą obsługę znaków spoza BMP. Zauważ, że to ograniczenie dotyczy tylko znaków spoza BMP w tekście wklejanym do plików przeznaczonych do edycji za pomocą edytorów Overleaf. Istnieją też inne sposoby uzyskiwania dostępu do znaków emoji:

* Używanie prymitywnych poleceń `\char"<punkt kodowy>` lub `\Uchar"<punkt kodowy>` (zob. [tę sekcję](#optional-detail-luatexluahbtex-char-vs-uchar) artykułu).
* Używanie plików tekstowych wejściowych zawierających znaki emoji w formacie UTF-8.
* Używanie poleceń LaTeX (makr), które wstawiają znaki emoji.

#### Wklejanie emoji i innych znaków spoza BMP do Overleaf

Jeśli wkleisz znak emoji, na przykład 😀, do Edytora Kodu Overleaf, zostanie on obecnie zamieniony na znaki ��.

![Błąd wynikający z kopiowania i wklejania znaków spoza BMP do edytorów Overleaf](/files/6ed9f52229b6ae7014e3de63af53d2b5ab9c6ed9)

Znak � ma w Unicode punkt kodowy FFFD, a jego oficjalna nazwa to REPLACEMENT CHARACTER i służy do „[zastępowania nieznanego, nierozpoznanego lub niemożliwego do przedstawienia znaku](https://en.wikipedia.org/wiki/Specials_\(Unicode_block\))”.

### Używanie punktów kodowych Unicode (U+) w LuaLaTeX

Dokumentacja Unicode przedstawia wartości punktów kodowych za pomocą zapisu `U+<wartość szesnastkowa>`— takie jak `U+1F600`, gdzie `1F600` to `<wartość szesnastkowa>` punktu kodowego Unicode dla znaku emoji 😀. Aby używać tych wartości punktów kodowych w LuaLaTeX, usuwa się `U+` i zapisuje `\char"<wartość szesnastkowa>` lub `\Uchar"<wartość szesnastkowa>`. Pakiet `"` znak informuje silnik TeX, że podana liczba jest określona w systemie szesnastkowym. Na przykład, aby użyć emoji 😀, zapiszesz `\char"1F600` lub `\Uchar"1F600`— używając czcionki zdolnej do jego składu.

Minimalny przykład LuaLaTeX z użyciem `\char` i `\Uchar` do składu znaku emoji 😀 mógłby wyglądać tak:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz]{NotoColorEmoji.ttf}
%Użyj \emojifont w grupie, aby ograniczyć jej działanie lokalnie
{\emojifont
\Uchar"1F600
\char"1F600}
\end{document}
```

[Otwórz ten przykład LuaLaTeX w 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)

**(szczegół opcjonalny) LuaTeX/LuaHBTeX: \char kontra \Uchar**

Oprócz konwencjonalnego `\char<kod znaku>` polecenia dla składu określonego `<kodu znaku>`, przy użyciu bieżącej czcionki, silniki LuaTeX, LuaHBTeX i XeTeX udostępniają również `\Uchar<kod znaku>` Z perspektywy użytkownika wynik `\char` i `\Uchar` wygląda tak samo, ale istnieje subtelna różnica w sposobie działania tych poleceń, jak zauważamy poniżej.

**Kluczowa różnica: rozwijanie**

`\Uchar` jest tak zwanym [rozwijalnym poleceniem](/latex/pl/artykuly-szczegolowe/22-how-does-expandafter-work-the-meaning-of-expansion.md#expansion-a-general-term-for-a-set-of-operations) natomiast `\char` nie jest rozwijalne. Gdy `\char<kod znaku>` lub `\Uchar<kod znaku>` polecenie jest „wykonywane” — tj. polecenie nie jest przechowywane jako część makra ani innej listy tokenów — w silniku TeX zachodzą następujące działania:

* **`\char<kod znaku>`** nakazuje silnikowi TeX natychmiast wstawić token znaku, reprezentujący `<kodu znaku>`, do dowolnej treści, którą aktualnie składa.
* W przeciwieństwie do tego, **`\Uchar<kod znaku>`** ma dwa odrębne etapy przetwarzania:

1. Ta `\Uchar<kod znaku>` polecenie jest *rozwinięty*rozwijane, `<kodu znaku>` a [tokenem znaku](/latex/pl/artykuly-szczegolowe/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#tex-tokens-101-28and-notions-of-expansion29) jest przekształcany w tymczasową listę tokenów zawierającą pojedynczy `<kodu znaku>`.
2. który reprezentuje *udostępniana* silnikowi TeX jako źródło jego następnego wejścia. W efekcie silnik TeX „tymczasowo odwraca uwagę”, używając tej pojedynczej listy tokenów jako miejsca swojego następnego elementu wejściowego (tokena). Domyślnie silnik TeX po prostu wraca, aby odczytać (wczytać) ten token i złożyć odpowiadający mu znak, odtwarzając zachowanie `\char` polecenie. **Jednak**, ponieważ ten `<kodu znaku>` nie został od razu złożony, lecz tymczasowo *zapisane* (zapisany) jako pojedynczy token, prymitywne polecenia TeX lub makra LaTeX mogą wykorzystać (pochłonąć) ten token — nie musi on zostać złożony od razu, lecz może zostać użyty w dalszym przetwarzaniu zgodnie z potrzebą.

W efekcie, `\char<kod znaku>` oznacza „złóż ten `<kodu znaku>` teraz”, podczas gdy `\Uchar<kod znaku>` ma formę „opóźnionego działania”, ponieważ tworzy przechowywany token znaku i udostępnia go jako następny element wejściowy (token). Ten token może zostać albo użyty (pochłonięty) przez polecenia i makra TeX, albo ponownie odczytany przez silnik TeX i złożony.

### Unicode (kodowanie) to nie cała historia

Możliwość używania znaków emoji w tekście zakodowanym w Unicode to tylko część sukcesu emoji. Wzrost użycia emoji był także możliwy dzięki rozwojowi [technologii czcionek OpenType](https://learn.microsoft.com/en-us/typography/opentype/)— czcionek, których dane glifów (projekty znaków) mogą zawierać [dane kolorowe](https://learn.microsoft.com/en-us/typography/opentype/spec/colr): tak zwane [kolorowych czcionek OpenType](#opentype-color-fonts).

Poza odpowiednimi czcionkami używanie kolorowych emoji wymaga dodatkowych komponentów oprogramowania, których zadania obejmują:

* wstępne przetwarzanie („[kształtowanie](#the-concept-of-text-shaping)”) tekstu zakodowanego w Unicode, *przygotowywanie* go do wyświetlenia przy użyciu określonej czcionki;
* *renderowanie i wyświetlanie* kolorowych emoji *glifów* na ekranie urządzenia.

#### Glif kontra znak: czy to nie to samo?

Określenia „glif” i „znak” są często używane tak, jakby były wymienne — odnosząc się do tej samej podstawowej koncepcji — ale istnieje subtelna, choć ważna, różnica w ich znaczeniu.

Unicode [definiuje termin „znak”](http://www.unicode.org/glossary/#character) jako:

> „Najmniejszy składnik języka pisanego, który ma wartość semantyczną; odnosi się do abstrakcyjnego znaczenia i/lub kształtu, a nie do konkretnej postaci…”

W przeciwieństwie do tego „glif” jest *konkretnym* *kształt* (projektowym) *wizualnym przedstawieniem* określonego *znaku*.

Problem znaku kontra glif można łatwo zaobserwować, gdy tekst zawierający emoji jest oglądany w różnych systemach/platformach oprogramowania, na przykład podczas czytania tego samego tekstu na telefonie komórkowym z iOS lub Androidem albo na komputerze stacjonarnym z Windows. Niezależnie od użytego urządzenia lub platformy, podstawowy tekst (sekwencja znaków) zawierałby te same zakodowane w Unicode *emoji* *znaki*. To możliwości zależne od urządzenia, związane z *wstępnym przetwarzaniem* tego tekstu, a następnie *renderowaniem* i *blokowym* wyników, być może z użyciem czcionek specyficznych dla urządzenia, powodują powstawanie różnych glifów (projektów znaków) reprezentujących te same znaki emoji.

Unicode’s [Pełna lista emoji](https://unicode.org/emoji/charts/full-emoji-list.html) udostępnia przykładowe obrazy reprezentujące każdy znak emoji Unicode — pokazujące różne glify używane przez różnych dostawców technologii. Projektanci czcionek nie tylko przyjmują własne, specyficzne projekty (glify) do reprezentowania znaków emoji, ale poszczególne czcionki różnią się też liczbą znaków emoji, które obsługują (dla których zawierają glify), i mogą zawierać lub nie bardziej zaawansowane funkcje przetwarzania tekstu emoji zawarte w specyfikacjach emoji Unicode.

Pojęcie i koncepcja znaków, ich semantyka i kodowanie stanowią podstawę świata Unicode: dotyczy on znaków. Projekt i wizualna reprezentacja poszczególnych znaków jako glifów należą do technologii czcionek i sztuki projektowania czcionek.

#### Emoji Unicode: znacznie więcej niż kodowanie tekstu

Podstawową rolą Unicode jest zapewnienie globalnego standardu kodowania, który określa, jaka wartość całkowita, zwana *punktem kodowym,* powinna być użyta do reprezentacji każdego znaku, w tym emoji, w strumieniu tekstu zakodowanego w Unicode.

Specyfikacja emoji w Unicode definiuje również *zachowania przetwarzania* dla niektórych *sekwencje* sekwencji znaków emoji pojawiających się w strumieniu tekstu zakodowanego w Unicode. Zdefiniowane sekwencje znaków emoji mogą być „łączone” poprzez proces zwany [kształtowaniem tekstu](#the-concept-of-text-shaping) aby utworzyć jeden wynikowy („złożony”) glif emoji — ten pojedynczy glif byłby używany przez system operacyjny urządzenia do reprezentowania oryginalnej sekwencji znaków obecnej w tekście.

Techniczny raport Unicode na temat [Unicode Emoji](https://unicode.org/reports/tr51/) dokumentuje bogaty zestaw funkcji dostępnych dla oprogramowania, które chce zapewnić zgodne z Unicode przetwarzanie znaków emoji. Na przykład Unicode definiuje (koduje) znaki zwane [modyfikatorami emoji](http://www.unicode.org/reports/tr51/#Emoji_Modifiers_Table) które można używać do generowania *wariacji* „bazowych” znaków emoji, takich jak wariacje [odcienia skóry na podstawie skali Fitzpatricka](http://www.unicode.org/reports/tr51/#Diversity). Zwróć uwagę, że zestaw podstawowych znaków emoji i stosowne modyfikatory są zdefiniowane jako część ogólnego [standardu emoji Unicode](http://www.unicode.org/reports/tr51).

Strona Unicode [Emoji Sequences](http://unicode.org/emoji/charts/emoji-sequences.html) udostępnia wykres sekwencji obecnie określonych przez specyfikację Unicode. Umieść wskaźnik myszy nad którymkolwiek z obrazów glifów emoji, aby zobaczyć małą podpowiedź informującą o podstawowej sekwencji znaków emoji Unicode, która tworzy dany glif:

![EmojiSequenceChart.png](/files/559cb9fd9cfa7a5e372a0bdf438e77da2e0a9b69)

Na przykład glif emoji:

![HandMediumSkinTone.png](/files/da90e210480df35f9694e2e7711ed7cc489a8864)

jest wymieniony w [sekcji sekwencji modyfikatorów](http://unicode.org/emoji/charts/emoji-sequences.html#modifier_sequences) i jest tworzony przez dwuznakową sekwencję U+1F44B U+1F3FD. Te składowe znaki to:

U+1F44B:![UnicodeWavingHandDefault.png](/files/3c5c9652f186559ca8365e9c8e892e832e563f95) (MACHAJĄCA DŁOŃ)

U+1F3FD:![FitzPatrick3.png](/files/21ed5ffb96c4f5576256a6702ca4510b9d592e86) (MODYFIKATOR EMOJI FITZPATRICKA TYPU 4)

**Używanie modyfikatorów odcienia skóry w LuaHBTeX**

Poniższy przykład używa LuaHBTeX, aby zademonstrować użycie modyfikatorów emoji:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=HarfBuzz,SizeFeatures={Size=20}]{NotoColorEmoji.ttf}
Samotna machająca dłoń: {\emojifont\Uchar"1F44B}\par
Samodzielny modyfikator: {\emojifont\Uchar"1F3FD}\par
Wynik połączony: {\emojifont\Uchar"1F44B\Uchar"1F3FD}
\end{document}
```

[Otwórz ten przykład modyfikatorów emoji w LuaLaTeX w Overleaf](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)

Ten przykład generuje następujący wynik:

![ModifiersInLuaHBTeX.png](/files/a4fffaffa7b92de6129a0954ddf3b59249932956)

#### UTF-8: jego rola w przechowywaniu tekstu Unicode

Każdy tekst lub kod wpisany albo wklejony do Edytora Kodu Overleaf (lub Edytora Wizualnego) będzie przechowywany w formacie UTF-8, więc pokrótce omówimy, co właściwie oznacza UTF-8. UTF oznacza Unicode Transformation Format, a rola UTF-8 w przechowywaniu lub przesyłaniu tekstu zakodowanego w Unicode jest wskazana przez frazę „Transformation *Format*”.

Wartości punktów kodowych Unicode mieszczą się w zakresie od 0 do maksymalnie 1 114 111, więc niemożliwe jest przedstawienie wszystkich wartości znaków Unicode przy użyciu pojedynczego 8-bitowego bajtu, który może przechowywać tylko do 256 różnych wartości: od 0 do 255. Jednak dowolny całkowity punkt kodowy Unicode można przedstawić za pomocą *ciągłej sekwencji* wartości bajtowych — i to jest zasada działania UTF-8.

UTF-8 dostarcza „przepisu”, aby *przekształcić* (tj. „zakodować” lub „konwertować”) wartość całkowitą punktu kodowego Unicode w unikalną sekwencję od 1 do 4 kolejnych bajtowych wartości całkowitych: liczba kolejnych bajtów wymaganych do użycia zależy od wartości całkowitej punktu kodowego. W konsekwencji można spotkać się z opisem UTF-8 przechowującego znaki Unicode jako *sekwencje wielobajtowe* ponieważ pojedynczy znak Unicode (wartość całkowita punktu kodowego) jest reprezentowany w UTF-8 jako sekwencja od 1 do 4 kolejnych bajtów.

Naturalnie tekst przechowywany w UTF-8 można przekształcić z powrotem do jego pierwotnej sekwencji całkowitych wartości punktów kodowych Unicode — to właśnie muszą zrobić XeTeX lub LuaTeX/LuaHBTeX, gdy odczytują plik wejściowy LaTeX zapisany w formacie UTF-8. Te silniki TeX muszą znać wejściowe wartości punktów kodowych Unicode (znaków), zanim będą mogły złożyć tekst. Zauważ, że pdfTeX nie ma wbudowanej możliwości dekodowania UTF-8, więc musi polegać na makrach TeX do przetwarzania (dekodowania) tekstu wejściowego sformatowanego w UTF-8.

**Kilka przykładów UTF-8**

* Arabski znak ش („sheen”) ma punkt kodowy Unicode 0634 w systemie szesnastkowym (podstawa 16) lub 1588 w systemie dziesiętnym (podstawa 10). W UTF-8 ش jest reprezentowany przez 2 (szesnastkowe) wartości D8 i B4, więc znak ش byłby przechowywany jako dwa kolejne bajty D8B4 w tekście zakodowanym UTF-8.
* Znak emoji 😀 ma punkt kodowy Unicode 1F600 w systemie szesnastkowym (podstawa 16) lub 128512 w systemie dziesiętnym (podstawa 10). W UTF-8 😀 jest reprezentowany przez 4 (szesnastkowe) wartości F0, 9F, 98 i 80, więc znak 😀 byłby przechowywany jako 4 kolejne bajty F09F9880 w pliku tekstowym UTF-8.

#### Znaki specjalne używane w przetwarzaniu tekstu emoji opartego na Unicode

Nie każdy znak zakodowany w Unicode jest przeznaczony do wizualnej prezentacji za pomocą glifów w czcionce: niektóre zakodowane znaki są oznaczone jako *znaki niedrukowalne* których zadaniem jest wspomaganie specjalistycznych funkcji przetwarzania tekstu (w obsługującym oprogramowaniu). Różne aplikacje zapewniają różny poziom obsługi znaków niedrukowalnych zakodowanych w Unicode, więc wynik będzie zależał od środowiska programowego — aplikacji i czcionek — które są używane.

**Dwa znaki niedrukowalne, o których warto wiedzieć**

* **Łącznik o zerowej szerokości (ZWJ)**, punkt kodowy 200D (szesnastkowo), jak sama nazwa wskazuje, jest przeznaczony do wyzwalania „zachowania łączenia” znaków wejściowych — ale tylko wtedy, gdy te znaki wejściowe *posiadają* określone zachowanie łączenia.
* **Niełącznik o zerowej szerokości (ZWNJ)**, punkt kodowy 200C (szesnastkowo), jest przeznaczony do *zapobiec* „zachowania łączenia”, które znaki wejściowe mogłyby w innym przypadku wykazywać. Na przykład można użyć ZWNJ, aby zapobiec łączeniu się kolejnych arabskich znaków, które normalnie byłyby przetwarzane (kształtowane) w swoje formy łączące.

Unicode opublikował listę [zalecanych sekwencji emoji ZWJ](https://unicode.org/emoji/charts/emoji-zwj-sequences.html) które używają U+200D ZERO WIDTH JOINER (ZWJ), aby połączyć sekwencje znaków emoji w jeden złożony glif emoji — jeśli jest on dostępny w używanej czcionce (czcionkach).

**Przykładowe użycie niełącznika o zerowej szerokości**

Poniższy minimalny fragment kodu używa czcionki OpenType Scheherazade, dołączonej do TeX Live, aby zdefiniować czcionkę LaTeX o nazwie `\arabicfont` której możemy użyć do składu pewnego tekstu arabskiego. Wiersz

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

używa znaku niełączącego o zerowej szerokości, poprzez `\Uchar"200C`, aby zapobiec normalnemu zachowaniu łączenia dwóch arabskich liter ل (lam) i ا (alef). Zwróć uwagę na użycie `\textdir TRT` do ustawienia kierunku tekstu jako od prawej do lewej:

```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}
```

[Otwórz ten przykład LuaLaTeX w 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)

Ten przykład generuje następujący wynik:

![NonJoiner.png](/files/6ac5fd22ec4c62d79805c39e1250c40d59101596)

## Pojęcie „kształtowania tekstu”

Zacznijmy od przykładu wizualnego z użyciem urduńskiego tłumaczenia słowa „edukacyjny”. Tekst tego tłumaczenia urdu można wpisywać na klawiaturze lub urządzeniu z ekranem dotykowym i byłby on tworzony jako prosta, liniowa sekwencja arabskich znaków Unicode. Jednak gdy taki tekst jest składany lub wyświetlany na ekranie urządzenia w [stylu Nastaliq](https://en.wikipedia.org/wiki/Nastaliq)wynik stanowi złożony dwuwymiarowy układ glifów.

Korzystając z naszego przykładu urdu, poniższa grafika porównuje liniowy zapis wejściowy arabskiego Unicode *znaki* z wynikiem składanym w stylu Nastaliq, obejmującym dwuwymiarowy układ *glifów* obecnych w (darmowej) czcionce [Awami Nastaliq](https://software.sil.org/awami/download/):

![](/files/e2525bc8d55a6ec33eb86edb76f9e2f25ef22e1a)

Proces „tłumaczenia” znaków wejściowych na zbiór prawidłowo rozmieszczonych glifów wyjściowych nazywa się *kształtowaniem tekstu*kształtowaniem tekstu

Kształtowanie tekstu jest niezbędne przy używaniu systemów pisma (systemów zapisu) takich jak [arabski](https://en.wikipedia.org/wiki/Arabic), [hebrajski](https://en.wikipedia.org/wiki/Hebrew_language), [Devanagari](https://en.wikipedia.org/wiki/Devanagari) lub [malajalam](https://en.wikipedia.org/wiki/Malayalam)język urdu, *złożonych skryptów*. Aby zapewnić poprawne przedstawienie tekstu w tych systemach pisma i językach, które ich używają, proces kształtowania musi starannie uwzględniać wszelkie reguły i niuanse kształtowania obecne w danej kombinacji systemu pisma i języka. Na przykład niektóre języki wymagają, aby wiele znaków wejściowych tworzyło określony glif wyjściowy, albo mogą istnieć złożone wymagania dotyczące precyzyjnego pozycjonowania znaków diakrytycznych oraz przestawień międzyglifowych, aby zapewnić prawidłowe wzajemne rozmieszczenie poszczególnych glifów.

Ogólnie rzecz biorąc, kształtowanie fragmentu tekstu wymaga kilku informacji:

* System pisma lub *pismo* język, w którym tekst jest zapisany.
* Konkretny *język* używany. Poszczególne pisma mogą być używane w wielu językach, przy czym każda kombinacja pisma i języka ma własne subtelności/niuansy kształtowania.
* Pisanie *kierunek* tekstu — na przykład od prawej do lewej lub od lewej do prawej.
* Skopiowany *czcionkę* który dostarcza glify potrzebne do odwzorowania ukształtowanego tekstu i opcjonalnie zawiera dodatkowe „reguły kształtowania”, które prowadzą proces kształtowania tekstu.

Wymagania dotyczące kształtowania tekstu, zwłaszcza w przypadku złożonych pism i powiązanych z nimi języków, mogą być niezwykle szczegółowe i subtelne, co wskazuje na potrzebę specjalistycznego oprogramowania, które może stosować potencjalnie bardzo złożone „reguły” kształtowania tekstu. Nic dziwnego, że takie oprogramowanie istnieje i określa się je jako *silnik kształtowania tekstu*; ten, o którym będziemy mówić, nazywa się [HarfBuzz](https://en.wikipedia.org/wiki/HarfBuzz), którego dokumentację warto przeczytać — na przykład [Dlaczego potrzebuję silnika kształtowania tekstu?](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html).

**Dalsza lektura o kształtowaniu tekstu**

Te krótkie wprowadzenia są gorąco polecane:

* [Czym jest kształtowanie tekstu?](https://harfbuzz.github.io/what-is-harfbuzz.html#what-is-text-shaping)
* [Dlaczego potrzebuję silnika kształtowania tekstu?](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html)

**Uwaga techniczna: wiele technologii (modeli) kształtowania**

Silnik kształtowania tekstu HarfBuzz obsługuje kilka „technologii kształtowania”, które różnią się sposobem implementacji procesu kształtowania — każda implementacja jest określana jako *moduł kształtujący*, w tym w `luaotfload` dokumentacji. Głównym tematem tego artykułu jest kształtowanie OpenType, ale alternatywną, darmową technologią jest [Graphite](https://scripts.sil.org/cms/scripts/page.php?site_id=projects\&item_id=graphite_aboutOT), opracowana przez [SIL International](https://www.sil.org/). Innym modelem kształtowania obsługiwanym przez HarfBuzz jest [Apple Advanced Typography (AAT)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html)— fonty obsługujące AAT są zazwyczaj używane na platformach technologicznych Apple.

**Przykład użycia modułu kształtującego Graphite**

Poniższy przykład składa tekst urdu przy użyciu fontu o nazwie [Awami Nastaliq](https://software.sil.org/awami/download/), który obsługuje kształtowanie Graphite i jest dostępny na Overleaf. Awami Nastaliq został stworzony przez [SIL International](https://www.sil.org/), organizację odpowiedzialną za rozwój technologii Graphite.

Poniższy przykład pokazuje zaawansowane możliwości kształtowania fontów opartych na Graphite — zwróć uwagę, jak `luaotfload` deklaracja fontu wybiera kształtowanie Graphite za pomocą `shaper=graphite2`.

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

\font\urdutest={file:AwamiNastaliq-Regular.ttf:mode=harf;shaper=graphite2} at 100bp
% Technologia
\pardir TRT\textdir TRT \urdutest ٹیکنالوجی

\vskip 75bp

% Edukacyjny
\pardir TRT\textdir TRT \urdutest تعلیمی
\end{document}
```

[Otwórz ten przykład w 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)

Ten przykład generuje następujący wynik:

![](/files/6e15caf030352afab3d334de849a11bf41d3a899)

#### Emoji i kształtowanie tekstu

Kształtowanie tekstu zostało wprowadzone za pomocą przykładów z języka o złożonym piśmie, urdu. Jednak może zaskakiwać fakt, że wyrenderowanie poprawnych glifów emoji wymaga zastosowania kształtowania tekstu do tekstu Unicode zawierającego sekwencje znaków emoji —[jak zauważył główny programista HarfBuzz](https://github.com/harfbuzz/harfbuzz/issues/2428#issuecomment-639108677):

> ... kształtowanie emoji w HarfBuzz jest całkowicie w zakresie projektu i faktycznie konieczne, aby uzyskać emoji rodzinne, odcienie skóry itp.

Przyjrzymy się przykładom tego.

### Podział odpowiedzialności: silnik kształtowania tekstu + fonty OpenType

W praktyce kształtowanie tekstu jest „operacją wspólną”, czyli podziałem pracy, między logiką i regułami wbudowanymi w silnik kształtowania tekstu a dodatkowymi regułami i danymi kształtowania wbudowanymi w używany(e) font(y) — od teraz omawiamy kształtowanie oparte na OpenType *tylko*.

Aby przeprowadzić kształtowanie, silnik kształtowania tekstu zazwyczaj otrzymuje pewien tekst Unicode, określone pismo i język, ewentualnie kierunek pisania, a przede wszystkim font OpenType do użycia podczas procesu kształtowania — font dostarczy wynik: zestaw glifów i danych pozycjonowania. Jeśli zostanie o to poproszony, silnik kształtowania może zastosować dodatkowe reguły ([funkcje OpenType](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features)) zawarte w używanym foncie OpenType — to, które reguły zastosować, zazwyczaj można wybrać z listy funkcji obsługiwanych przez font.

Wynikiem procesu kształtowania jest *lista glifów* zawartych w foncie OpenType, wraz z *międzyglifowymi* danymi pozycjonowania. Dane te odnoszą się do *względnego rozmieszczenia ukształtowanych glifów*; nie odnoszą się one do bezwzględnego pozycjonowania na składanej stronie ani w innych mediach/treściach, takich jak strona internetowa, Tweet itp. Oprogramowanie renderujące (silnik składu, przeglądarka internetowa itp.) wykorzystuje informacje o pozycjonowaniu między glifami, aby zapewnić prawidłowe wzajemne położenie glifów po ich złożeniu i włączeniu do końcowego wyniku.

#### Czym jest lista glifów?

Wewnętrznie każdemu glifowi w foncie OpenType przypisuje się numeryczny identyfikator, wartość całkowitą zwaną indeksem glifu — nazywanym też identyfikatorem glifu lub GID. Po zakończeniu zadania kształtowania silnik kształtowania tekstu zwróci wyniki jako *listę identyfikatorów glifów* plus *dane pozycjonowania* dla tych glifów.

Poszczególnym glifom w fontach OpenType twórca fontu przypisuje indeksy (identyfikatory), co czyni je bardzo specyficznymi dla danego fontu i arbitralnymi wartościami — mogą one także różnić się między wersjami danego fontu. Nigdy nie należy zakładać, że ta sama wartość GID będzie odpowiadać „podobnym” glifom w różnych fontach; niemal na pewno tak nie będzie. Jeśli masz listę identyfikatorów glifów dostarczoną przez silnik kształtowania, możesz używać ich tylko do uzyskiwania dostępu do glifów w foncie, z którego zostały pobrane.

#### Czym są fonty OpenType?

Sieć jest *pełna* wyjaśnień i szczegółów dotyczących fontów OpenType, więc ograniczymy się do krótkiego opisu.  [specyfikacja OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/) jest złożonym dokumentem przeznaczonym dla deweloperów, ale w istocie definiuje format pliku, czyli kontener, dla danych fontu. Font OpenType zawiera dane opisujące kształty glifów, wraz z informacjami o obsługiwanym piśmie (pismach) i języku (językach), metadanymi o foncie oraz różnymi „tabelami”, które definiują [cechy typograficzne](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features) obsługiwane przez font.

Silnik kształtowania tekstu można zazwyczaj polecić, aby selektywnie stosował (używał) funkcje fontu podczas procesu kształtowania, stosując określone efekty typograficzne („reguły”), które wybierają odpowiedni zestaw glifów zawartych w foncie. Wybrany font będzie musiał obsługiwać i dostarczać glify dla wszelkich funkcji, których zastosowania zażąda silnik kształtowania tekstu.

#### Zakodowane i niezakodowane „glify”

Fonty OpenType zawierają tabelę danych zwaną [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) (Character to Glyph Index Mapping), która mapuje zestaw znaków Unicode obsługiwanych przez font na odpowiadający im indeks glifu w tym foncie. Poniższy film daje krótkie spojrzenie na tabelę cmap zawartą w foncie o nazwie `lmmono10-regiular.otf` (dołączonym do TeX Live).

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

Jednak fonty zazwyczaj zawierają wiele glifów, które nie reprezentują konkretnego znaku Unicode i nie są częścią tej tabeli cmap. W rezultacie zestaw glifów obecnych w foncie OpenType można podzielić na dwa główne zbiory:

* zakodowane glify reprezentujące znaki Unicode;
* niezakodowane glify, które nie reprezentują znaków Unicode.

Do zakodowanych glifów można uzyskać dostęp, umieszczając w tekście odpowiedni znak Unicode — ale co z glifami niezakodowanymi, jak się ich używa/uzyskuje do nich dostęp? Glify te są zazwyczaj używane jako wynik operacji kształtowania tekstu, w tym stosowania funkcji fontu w celu uzyskania określonych efektów wizualnych/typograficznych.

### kolorowych czcionek OpenType

Oczekuje się, że znaki emoji będą wyświetlane/renderowane w pełnym kolorze — czarno-białe emoji nie zapewniają do końca „pełnego doświadczenia emoji”. Jednak w czasie początkowego kodowania emoji w Unicode [specyfikacja fontów OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/) nie zawierała odpowiednich rozwiązań do osadzania *colorful*danych -glifowych w fontach OpenType. Ta „luka” w OpenType skłoniła czołowych dostawców technologii/platform do poszukiwania rozwiązań, a wynikający z tego „wyścig” doprowadził do [różnych propozycji rozszerzenia OpenType](https://www.fontlab.com/news/color-font-format-proposals/) w celu obsługi kolorowych fontów OpenType — nie tylko do wyświetlania kolorowych znaków emoji (glifów), lecz do renderowania dowolnego glifu w kolorze.

#### Cztery odmiany kolorowych fontów OpenType

[Adobe, Microsoft, Google i Apple przedstawiły po jednej propozycji](https://www.fontlab.com/news/color-font-format-proposals/) rozszerzenia OpenType o obsługę pełnokolorowych fontów OpenType i ostatecznie przyjęto cztery propozycje, które włączono do formalnej specyfikacji OpenType. Dla wygody możemy je z grubsza podzielić na wektorowe i rastrowe — ale, jak pokazano w tym [repozytorium GitHub](https://github.com/simoncozens/test-fonts), specyfikacja OpenType jest wystarczająco elastyczna, aby obsługiwać pliki kolorowych fontów OpenType łączące te cztery podstawowe technologie.

* **Wektorowe fonty OpenType:**
* **Microsoft**: kształty glifów są opisywane za pomocą formy warstwowych wektorów koloru ([COLR](https://docs.microsoft.com/en-us/typography/opentype/spec/colr) i [CPAL](https://docs.microsoft.com/en-us/typography/opentype/spec/cpal) tabele).
* [**Adobe i Mozilla**](https://www.w3.org/2013/10/SVG_in_OpenType/) ([tabela SVG](https://docs.microsoft.com/en-us/typography/opentype/spec/svg)): kształty glifów są rysowane za pomocą SVG, które obsługuje glify zbudowane z wektorów *i obrazów rastrowych*. Zobacz też [przewodnik użytkownika Adobe dotyczący fontów SVG](https://helpx.adobe.com/fonts/user-guide.html/fonts/using/ot-svg-color-fonts.ug.html).
* **Rastrowe fonty OpenType:**
* **Google**: glify są reprezentowane przez kolorowe obrazy PNG osadzone w foncie ([CBDT](https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt) i [CBLC](https://docs.microsoft.com/en-us/typography/opentype/spec/cblc) tabele).
* **Apple**: glify również są reprezentowane przez kolorowe obrazy osadzone w foncie. Oprócz PNG mechanizm Apple ([tabela sbix](https://docs.microsoft.com/en-us/typography/opentype/spec/colr)) obsługuje także JPEG i TIFF.

W konsekwencji systemy operacyjne i oprogramowanie aplikacyjne obsługujące kolorowe fonty OpenType muszą radzić sobie z dzisiejszym mieszanym krajobrazem technologicznym. Ponadto należy mieć świadomość, że poszczególne kolorowe fonty OpenType — a także *wersje* tego samego fontu — będą:

* mieć różny zakres pokrycia pełnego zestawu [znaków emoji Unicode](https://unicode.org/emoji/charts/emoji-list.html)— tzn. dla ilu znaków emoji font dostarcza glify;
* używać różnych projektów glifów do reprezentowania poszczególnych znaków emoji;
* różnić się funkcjami, które oferują, aby obsługiwać bardziej zaawansowane zastosowania standardów Unicode, takie jak [modyfikatorami emoji](https://unicode.org/reports/tr51/#Emoji_Modifiers_Table)sekwencje łączenia emoji [Unicode Technical Standard #51: Unicode Emoji](https://unicode.org/reports/tr51/).

#### Szum wokół HarfBuzz

Wspomnieliśmy o potrzebie *silnik kształtowania tekstu*: oprogramowania, które pobiera wejściowy tekst Unicode zapisany przy użyciu określonej kombinacji pisma i języka i, używając wskazanego fontu, kształtuje ten tekst w sekwencję glifów wraz z danymi pozycjonowania, które można wykorzystać do złożenia oryginalnego tekstu wejściowego.

[HarfBuzz](https://harfbuzz.github.io/) jest właśnie takim silnikiem kształtowania tekstu: jest [biblioteką kodu open source](https://github.com/harfbuzz/harfbuzz) i efektem ponad dekady badań i rozwoju — nadal aktywnie rozwijaną i wdrażaną jako część wielu produktów programowych. Sam HarfBuzz nie wykonuje „składu”, lecz dostarcza „usługi kształtowania tekstu” oprogramowaniu, które decyduje się go zintegrować, w tym XeTeX, LuaHBTeX, [Adobe PhotoShop i Adobe InDesign](https://en.wikipedia.org/wiki/HarfBuzz).

Dzięki włączeniu HarfBuzz silniki TeX mogą korzystać z jego zaawansowanych możliwości kształtowania tekstu, aby zapewnić bardzo wyrafinowany wielojęzyczny skład, szczególnie dla złożonych pism takich jak arabski, hebrajski, dewanagari i wiele innych. Warto też zauważyć, że HarfBuzz jest używany do przetwarzania i kształtowania znaków tekstowych emoji Unicode, co omówimy bardziej szczegółowo.

Poniższa grafika podsumowuje rolę odgrywaną przez HarfBuzz, gdy jest zintegrowany z oprogramowaniem takim jak XeTeX lub LuaHBTeX, podczas składu tekstu w złożonym piśmie, takim jak arabski:

![Przegląd kształtowania tekstu arabskiego z HarfBuzz](/files/73f4cec306d50c9703c9fb5e607007403a4597a2)

**Poznajemy HarfBuzz**

Każdy, kto chce dowiedzieć się więcej o HarfBuzz i usługach kształtowania OpenType, które dostarcza XeTeX i LuaHBTeX, może [pobrać binarną dystrybucję HarfBuzz](https://github.com/harfbuzz/harfbuzz/releases) która zawiera bibliotekę HarfBuzz (dla programistów) oraz narzędzia wiersza poleceń `hb-view` i `hb-shape`.

**Przykład: jak używać hb-view**

Utwórz nowy plik w swoim ulubionym edytorze tekstu obsługującym UTF-8 i skopiuj/wklej następujące sześć znaków emoji 👋👋🏻👋🏼👋🏽👋🏾👋🏿 do tego pliku tekstowego, a następnie zapisz go w formacie UTF-8 do pliku o nazwie na przykład `emoji.txt`.

Zauważ, że twój edytor tekstu może wyświetlać (zastępcze) czarno-białe wersje emoji, ponieważ nie jest w stanie (nie jest zaprogramowany do) renderować kolorowych glifów. Gdy te 6 emoji zostanie zapisanych, plik `emoji.txt` powinien zawierać dane UTF-8 dla następującej sekwencji znaków emoji Unicode — oddzieliliśmy modyfikatory emoji przecinkami jedynie dla *czytelności*:

* `1F44B` aby uzyskać 👋
* `1F44B`, `1F3FB` aby uzyskać 👋🏻
* `1F44B`, `1F3FC` aby uzyskać 👋🏼
* `1F44B`, `1F3FD` aby uzyskać 👋🏽
* `1F44B`, `1F3FE` aby uzyskać 👋🏾
* `1F44B`, `1F3FF` aby uzyskać 👋🏿

Łącznie powinno być **11** znaków Unicode, z których każdy generuje 4 bajty danych UTF-8, więc wynikowy `emoji.txt` plik powinien mieć 44 bajty, z wyłączeniem znaczników końca linii użytych na końcu wiersza zawierającego emoji.

Ta `hb-view` narzędzie może użyć pliku `emoji.txt`, wraz z odpowiednim kolorowym fontem OpenType wybranym przez ciebie, takim jak `NotoColorEmoji.ttf`, aby wygenerować plik SVG z wyrenderowanym wynikiem HarfBuzz. Poniższy przykład wiersza poleceń, który musi być **wpisany w jednej linii** w twoim terminalu, wygeneruje plik SVG `emoji.svg`:

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

Po pomyślnym wykonaniu plik `emoji.svg`, wygenerowany przez `hb-view`, może zostać otwarty w Inkscape i powinien wyglądać mniej więcej tak:

![Hbvieemoji.png](/files/8c75a7c5abb45c57e3f51da5227952f5fa2f4ee7)

`hb-view` można użyć do badania kształtowania HarfBuzz dla dowolnego odpowiedniego pliku tekstowego Unicode i fontu OpenType — zdecydowanie nie ogranicza się to do emoji! Wpisz

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

aby zobaczyć bogactwo opcji wiersza poleceń tego potężnego i wygodnego narzędzia. Miłego kształtowania!

## Kształtowanie tekstu i silniki TeX

Tutaj omówimy możliwości kształtowania tekstu w XeTeX oraz rodzinie silników TeX LuaTeX.

### XeTeX

XeTeX został opracowany na początku lat 2000. i zapoczątkował kilka innowacji w składzie opartym na TeX, w szczególności *wbudowane* wsparcie dla:

* czytania tekstu Unicode w formacie UTF-8;
* używania fontów OpenType;
* kształtowania tekstu do składu wielojęzycznego;
* składu matematycznego opartego na OpenType.

Zdolność XeTeX do łatwego i wygodnego składu języków o złożonym piśmie wynika z jego wbudowanych możliwości kształtowania tekstu — pierwotnie opartych na, obecnie przestarzałym, [ICU LayoutEngine](http://userguide.icu-project.org/layoutengine). Dzięki pracy Khaleda Hosny’ego XeTeX przeszedł na używanie HarfBuzz do kształtowania tekstu, jak odnotowano w ogłoszeniu z [marca 2013](https://tug.org/pipermail/xetex/2013-March/024118.html). Dla każdego, kto chce składać tekst wielojęzyczny, XeTeX jest zwykle wskazywany jako preferowany silnik TeX — ale teraz istnieje inna opcja, LuaHBTeX, którą omówimy.

### LuaTeX i LuaHBTeX

Rozwój LuaTeX rozpoczął się około 2005 roku, ale kierował się filozofią projektową zupełnie inną niż XeTeX, który włączał nowe funkcje *bezpośrednio do* oprogramowania XeTeX. W przeciwieństwie do XeTeX, twórcy LuaTeX zdecydowali się „...zapewnić minimalny zestaw narzędzi i żadnych gotowych rozwiązań.” (zob. [Reference Manual for LuaTeX](https://www.pragma-ade.com/general/manuals/luatex.pdf)). Zamiast dostarczać zestawu dodatkowych funkcji *wbudowanych w* silniki oparte na LuaTeX, wewnętrzne mechanizmy silników LuaTeX są udostępniane, aby programiści i zaawansowani użytkownicy mogli wykorzystać zintegrowany język skryptowy Lua do tworzenia własnych rozwiązań.

Na przykład, w przeciwieństwie do XeTeX, silnik LuaTeX nie może *bezpośrednie* używać fontów OpenType; zamiast tego fonty OpenType muszą być ładowane i „przygotowywane do użycia” za pomocą funkcji ładowania fontów napisanych w kodzie Lua. Te funkcje ładowania fontów są określane jako *callback* funkcje: kod Lua, który LuaTeX wywoła („wykona”) po zgłoszeniu żądania załadowania fontu.

Ponadto silnik LuaTeX nie zapewnia żadnych *wbudowane* możliwości kształtowania tekstu — one również muszą być dostarczone przez zewnętrzny kod, do którego silnik LuaTeX może się odwołać, aby uzyskać usługi kształtowania tekstu. I tutaj również kontrastuje to z silnikiem XeTeX, który włączył możliwości kształtowania tekstu do podstawowego oprogramowania.

#### luaotfload: niezbędny do używania fontów OpenType w LuaTeX/LuaHBTeX

Mechanizm callbacków LuaTeX do ładowania fontów zapewnia dużą elastyczność, choć kosztem dodatkowego programowania. Na szczęście dla użytkowników LuaLaTeX społeczność TeX opracowała pakiet o nazwie `luaotfload`, który stanowi część [corocznej wersji TeX Live](https://www.tug.org/texlive/) i oczywiście jest dostępny dla użytkowników Overleaf.

`luaotfload` to [dostępny w CTAN](https://ctan.org/pkg/luaotfload?lang=en) i ma [repozytorium rozwojowe na GitHubie](https://github.com/latex3/luaotfload) gdzie możesz śledzić najnowsze zmiany i [nowe wydania](https://github.com/latex3/luaotfload/releases).

`luaotfload` można załadować bezpośrednio do preambuły dokumentu LaTeX za pomocą

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

Należy zauważyć, że `luaotfload` jest nazwą LaTeX *pakietu*, co oznacza, że ma nazwę pliku `luaotfload.sty`. Jeśli chciałbyś używać `luaotfload` z plain TeX, możesz to zrobić, dodając linię

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

do swojego dokumentu plain TeX.

Zwykle użytkownicy LuaLaTeX — czyli ci, którzy składają LaTeX przy użyciu LuaTeX/LuaHBTeX — nie muszą bezpośrednio zajmować się `luaotfload` ponieważ [`fontspec` pakietu](https://ctan.org/pkg/fontspec) załaduje `luaotfload` pakiet za ciebie, dbając o wiele szczegółów niskiego poziomu za pomocą poleceń na poziomie użytkownika udostępnianych przez `fontspec` pakiet.

### LuaHBTeX: nowe opcje kształtowania tekstu

`luaotfload` jest dojrzałą i potężną biblioteką Lua, która zapewnia obsługę fontów OpenType w LuaTeX — wraz ze świadczeniem usług kształtowania tekstu dla wielu języków i pism. Początkowo funkcje kształtowania tekstu `luaotfload` były zaimplementowane w czystym kodzie Lua, ale wydanie TeX Live 2020 przyniosło kolejną popularną opcję kształtowania tekstu — nowy silnik oparty na LuaTeX o nazwie LuaHBTeX.

„HB” w LuaHBTeX oznacza HarfBuzz — w istocie LuaHBTeX to oryginalny silnik LuaTeX *plus* z zintegrowanym silnikiem kształtowania tekstu HarfBuzz. Zgodnie z filozofią projektową LuaTeX dostępność HarfBuzz nie *automatycznie* gwarantuje, że tekst będzie kształtowany przez LuaHBTeX: HarfBuzz jest kolejnym narzędziem, którego można użyć do tworzenia rozwiązań kształtowania tekstu.

Integracja HarfBuzz w LuaHBTeX jest [programowalna za pomocą kodu Lua](#introduction-to-the-luahbtex-harfbuzz-api), co umożliwiło `luaotfload`deweloperom dodać rozwiązania kształtowania tekstu oparte na HarfBuzz. W konsekwencji, [począwszy od wersji 3.1, wydanej 5 listopada 2019](https://github.com/latex3/luaotfload/releases/tag/v3.1), `luaotfload` został ulepszony, aby korzystać z HarfBuzz — dzięki czemu możliwości kształtowania tekstu HarfBuzz stały się łatwo dostępne dla zwykłego użytkownika.

Czytelnicy zainteresowani technicznymi szczegółami integracji HarfBuzz z LuaTeX mogą przeczytać ten [artykuł autorstwa Khaleda Hosny’ego](https://www.tug.org/TUGboat/tb40-1/tb124hosny-harfbuzz.pdf).

### luaotfload: dwie opcje kształtowania tekstu (kiedy używać HarfBuzz?)

Użytkownicy LuaLaTeX mają teraz dwie opcje kształtowania tekstu:

* `luaotfload`oryginalna (oparta na węzłach) implementacja kształtowania tekstu, napisana wyłącznie w Lua;
* `luaotfload`kształtowanie oparte na HarfBuzz — dostępne za pomocą kodu Lua, który wywołuje funkcje kształtowania tekstu HarfBuzz.

`luaotfload` zapewnia dostęp do tych dwóch systemów kształtowania za pomocą swojego „`mode`” parametru — choć większość użytkowników użyje odpowiednika `fontspec` „`Renderer`” opcji, zamiast bezpośrednio używać funkcji niższego poziomu `luaotfload`.

Każda z `luaotfload`rozwiązań kształtowania tekstu ma swoje mocne strony i (obecne) słabości, ale którego z nich należy użyć i kiedy? Oto kilka punktów do rozważenia:

* `luaotfload`natywne przetwarzanie oparte na węzłach może być pamięciochłonne, zwłaszcza w przypadku dużych fontów OpenType CJK. Użycie HarfBuzz do kształtowania tekstu CJK może przynieść poprawę szybkości i zmniejszenie zużycia pamięci.
* Używaj HarfBuzz dla pism złożonych, ponieważ „...znacznie poprawia renderowanie pism indyjskich i arabskich i jest wysoce zalecany dla takich pism.” (zob. `luaotfload` podręcznik).
* Integracja HarfBuzz w `luaotfload` jest nadal stosunkowo nowa i podlega dalszemu rozwojowi. W chwili pisania tego tekstu (lipiec 2021) zaleca się używanie wbudowanego kształtowania luaotfload (ustawiając `mode=node`) dla głównych fontów dokumentu, szczególnie jeśli dokument używa pisma łacińskiego. Zobacz ten [zgłoszenie na GitHubie](https://github.com/latex3/luaotfload/issues/175#issue-801120377), które podsumowuje problemy i dyskusje. Jeśli chcesz poeksperymentować, możesz użyć `luaotfload` aby załadować plik fontu i utworzyć dwa fonty LaTeX: jeden używający kształtowania opartego na HarfBuzz, a drugi używający kształtowania opartego na Lua. Overleaf stworzył [przykładowy projekt](#sample-project-arabic-shaping), który to demonstruje.
* Nie używaj HarfBuzz do obsługi fontów matematycznych. Jak omówili deweloperzy na tex.stackexchange, HarfBuzz jest [nie jest przeznaczony do obsługi fontów do składu matematycznego](https://tex.stackexchange.com/questions/544881/does-luahbtex-with-harfbuzz-renderer-completely-supports-math-formating) więc nie używaj go w tym celu.

**Przykładowy projekt: kształtowanie tekstu arabskiego**

Oto projekt Overleaf, który używa kilku wysokiej jakości krojów arabskich, aby porównać `luaotfload`usługi kształtowania tekstu oparte na węzłach (`mode=node`)`mode=harf`):

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

Projekt ten zawiera wynik pokazany na poniższym obrazie:

![Skład arabskiego](/files/69882499b9fb2a4759c8d5c1b4a8849465bde1d1)

### Wybór „Renderera” w fontspec

Jak zauważono w jego [dokumentację](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), `fontspec` „...pozwala użytkownikom XeTeX lub LuaTeX ładować fonty OpenType w dokumencie LaTeX”. Jeśli używasz silników LuaTeX lub LuaHBTeX, `fontspec` załaduje `luaotfload` bibliotekę za ciebie, a ponadto zapewnić zestaw wygodnych poleceń na poziomie użytkownika, które zmniejszają potrzebę korzystania z `luaotfload`funkcjonalności niskiego poziomu.

Jak więc wybrać między kształtowaniem HarfBuzz a wbudowanym kształtowaniem zapewnianym przez `luaotfload`? Odpowiedź znajduje się w doskonałym [`fontspec` dokumentację](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), a konkretnie w Części VI: Funkcje fontów tylko dla LuaTeX. `fontspec` zapewnia ustawienie o nazwie `Renderer` które można ustawić podczas definiowania fontu za pomocą `fontspec`. `Renderer` steruje przetwarzaniem fontu na niskim poziomie. Dwie interesujące opcje to

* `Renderer = Node`: domyślny „tryb” składu fontów OpenType — używa on `luaotfload`funkcji kształtowania tekstu zaimplementowanych wyłącznie w Lua.
* `Renderer = Harfbuzz`: ten „tryb” definiuje/ładuje font do użycia z silnikiem kształtowania tekstu HarfBuzz. `luaotfload` używa API LuaHBTeX do wywoływania funkcji w HarfBuzz.

Więcej informacji znajdziesz w [`fontspec` dokumentację](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf).

## Silniki TeX, HarfBuzz i kolorowe emoji

Chociaż zarówno XeTeX, jak i LuaHBTeX integrują HarfBuzz, zapewniają różne poziomy obsługi niektórych bardziej zaawansowanych funkcji HarfBuzz — przede wszystkim ładowania i używania kolorowych fontów OpenType.

### XeTeX i kolorowe fonty OpenType

Jak zauważono, istnieją dwie kategorie kolorowych fontów OpenType, oparte na formacie danych używanym do przechowywania glifów fontu: wektorowe i rastrowe.

#### XeTeX i rastrowe kolorowe fonty OpenType

XeTeX nie może wczytywać rastrowych kolorowych czcionek OpenType — takich jak Google’a [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/) dołączonej do TeX Live 2020. Na przykład, jeśli spróbujesz wczytać Noto Color Emoji (NotoColorEmoji.ttf), XeLaTeX zakończy się niepowodzeniem z potencjalnie mylącym błędem twierdzącym, że Noto Color Emoji „nie można znaleźć”. Poniższy kod LaTeX, składany za pomocą XeLaTeX, *nie działa*:

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

[Otwórz ten kod XeLaTeX w Overleaf (on ***nie*** działa).](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)

Kończy się niepowodzeniem z błędem:

```
! Błąd pakietu fontspec: Czcionka "NotoColorEmoji" nie może zostać znaleziona.
```

Podobnie, prosty przykład Plain TeX przetworzony przez XeTeX również kończy się niepowodzeniem

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

[Otwórz ten przykład Plain TeX (XeTeX) w Overleaf (on ***nie*** działa).](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)

Przykład Plain TeX zgłasza podobny, ale inny komunikat błędu:

```
! Czcionka \emojifont=[NotoColorEmoji.ttf] at 12.0pt nie daje się wczytać: plik metryki (TFM)
lub zainstalowana czcionka nie została znaleziona.
l.1 \font\emojifont="[NotoColorEmoji.ttf]" at 12pt

Nie udało mi się odczytać danych o rozmiarze tej czcionki,
więc zignoruję specyfikację czcionki.
[Czarodzieje mogą naprawić pliki TFM za pomocą TFtoPL/PLtoTF.]
Możesz spróbować wstawić inną specyfikację czcionki;
np. wpisz `I\font<ten sam identyfikator czcionki>=<nazwa czcionki zastępczej>'.
```

**Przykład Plain LuaHBTeX**

Dla porównania, oto minimalny przykład Plain TeX skompilowany za pomocą LuaHBTeX

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

[Otwórz ten przykład Plain TeX (LuaHBTeX) w Overleaf (kompiluje się pomyślnie).](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)

#### Prawdziwa przyczyna niepowodzenia XeTeX

Komunikaty błędów udostępniane przez XeTeX częściowo zaciemniają rzeczywistą przyczynę problemu: kolorowe czcionki OpenType, zwłaszcza ich rastrowe warianty, *nie* są obsługiwane przez XeTeX. W rzeczywistości XeTeX (Kpathsea) może *znaleźć* czcionkę Noto Color Emoji, ale XeTeX nie może jej w pełni *wczytać* tej czcionki i nie jest w stanie zainicjalizować wewnętrznych tabel danych czcionki wymaganych do użycia jej w składaniu tekstu. Wewnętrznie XeTeX *zaczyna się* proces wczytywania czcionki i testuje ją pod kątem „skalowalności” (według definicji „skalowalności” używanej przez FreeType), ale ten test kończy się niepowodzeniem, a XeTeX zgłasza standardowy, być może mylący, komunikat błędu silnika TeX.

**Uwaga techniczna**

Przetwarzanie pliku NotoColorEmoji.ttf przez XeTeX zostało zbadane przez skompilowanie debugowej wersji wykonywalnego pliku XeTeX. Do ustawienia punktu przerwania na funkcji XeTeX użyto środowiska Eclipse IDE `creatFontFromFile(filename, index, pointsize)`, a następnie wykonywano krok po kroku kod, aby obserwować dalsze przetwarzanie.

#### XeTeX i wektorowe kolorowe czcionki OpenType

XeTeX może *wczytać* wektorowe kolorowe czcionki OpenType, ale nie wygeneruje kolorowych emoji w wynikowym pliku PDF — o ile XeTeX w ogóle taki plik wygeneruje. W przeciwieństwie do LuaTeX, LuaHBTeX i pdfTeX, XeTeX nie *bezpośrednie* wyprowadza składanych dokumentów w formacie PDF. Zamiast tego XeTeX tworzy pośredni `.xdv` (po**x**szerzony **dv**i) format pliku, który jest konwertowany do PDF przez narzędzie o nazwie `xdvipdfmx`. Na czas pisania tego tekstu, `xdvipdfmx` nie jest w stanie osadzić odpowiednich danych kolorowych glifów emoji w pliku PDF, więc w najlepszym razie zobaczysz monochromatyczne emoji — wynik „zapasowy” — w PDF-ie, a w zależności od użytej czcionki być może nie zobaczysz niczego.

Oto przykład XeLaTeX, który używa kolorowej czcionki OpenType [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr), dostępnej w TeX Live. TwemojiMozilla.ttf używa wektorowego formatu COLR/CPAL firmy Microsoft do przechowywania kolorowych glifów i jest dołączona do TeX Live 2020. W tym przykładzie XeTeX jest w stanie wczytać czcionkę, wygenerować `.xdv` plik XDV i PDF, ale glif emoji nie jest obecny w składanym pliku PDF:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}
\newcommand{\smiley}{{\emojifont\char"1F600}}
Oto uśmieszek: \smiley
\end{document}
```

[Otwórz ten kod XeLaTeX w Overleaf (NIE DZIAŁA).](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)

W przeciwieństwie do tego powyższy kod działa z LuaLaTeX, jeśli zdefiniujesz `\emojifont` przy użyciu `fontspec` ustawienie `[Renderer=HarfBuzz]`:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}[Renderer=HarfBuzz]
\newcommand{\smiley}{{\emojifont\char"1F600}}
Oto uśmieszek: \smiley
\end{document}
```

[Otwórz ten kod LuaLaTeX w Overleaf (działa).](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 i kolorowe czcionki OpenType

Dzięki zintegrowanemu silnikowi składania HarfBuzz oraz bibliotece `luaoftload` LuaHBTeX obsługuje wszystkie cztery odmiany kolorowych czcionek OpenType. Użytkownicy LuaLaTeX mogą w pełni korzystać z przetwarzania tekstu opartego na Unicode, zawierającego znaki emoji, albo po prostu urozmaicać swoje dokumenty bardzo kolorowym tekstem przy użyciu kolorowych czcionek OpenType.

Jak wspomniano wcześniej, cztery warianty kolorowych czcionek OpenType można podzielić na dwie grupy:

* te zawierające glify w rastrowych formatach obrazu, takich jak PNG;
* inne, które używają wektorowych formatów SVG lub mechanizmu COLR/CPAL firmy Microsoft.

Wektorowe formaty glifów mają zaletę skalowalności: zapewniają ostre grafiki glifów przy dowolnym rozmiarze punktowym.

**Używanie kolorowych czcionek Microsoft COLR/CPAL z LuaHBTeX**

Jeśli chcesz używać wektorowego formatu dla swoich kolorowych czcionek emoji OpenType, sprawdź czcionkę [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr?lang=en), która opiera się na formacie COLR/CPAL firmy Microsoft. TwemojiMozilla.ttf jest dołączona do TeX Live, ale najnowszą wersję możesz pobrać z jej [repozytorium GitHub](https://github.com/mozilla/twemoji-colr/releases) i przesłać ją do swojego projektu w Overleaf.

Oto mały, `fontspec`-oparty przykład używający `Renderer=Harfbuzz`, który składa dużą (wektorową) kaczkę emoji:

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

[Otwórz ten przykład LuaLaTeX, aby złożyć wektorową kaczkę.](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)

Oto (wektorowa) kaczka wygenerowana przez powyższy przykład:

![](/files/7b37b51a2c20fa8795b007c52fbccfd6dfab8c93)

#### Korzystanie z kolorowych czcionek OpenType opartych na SVG z LuaHBTeX

W chwili pisania tej aktualizacji artykułu (lipiec 2023) istnieje niewiele formalnej dokumentacji dotyczącej używania kolorowych czcionek OpenType w odmianie SVG z LuaLaTeX. Niektóre [uwagi zamieszczone w dyskusjach online](https://github.com/latex3/luaotfload/issues/96) sugerują użycie `fontspec`jego `RawFeature`, jak pokazano w poniższym pseudokodzie. Zastąp `*nazwa twojego pliku czcionki SVG tutaj*` nazwą pliku czcionki opartej na SVG, do którego ma dostęp twój kod LaTeX:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emoji[RawFeature={+svg},SizeFeatures={Size=20}]{your SVG font file name here}
\emoji Twoje emoji tutaj...
\end{document}
```

Jeśli pominiesz `fontspec` i wczytasz `luaotfload` bezpośrednio, może być konieczne zadeklarowanie i określenie czcionki w następujący sposób — nasze eksperymenty wskazują, że trzeba pominąć `mode=harf` opcję, aby to działało:

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

**Kilka ostrzeżeń**

Czytelnicy zainteresowani używaniem kolorowych czcionek OpenType w odmianie SVG powinni pamiętać, że:

* czcionki OpenType w odmianie SVG zawierające dużą liczbę glifów mogą być [obliczeniowo kosztowne dla LuaLaTeX](#processing-svg-glyph-data) w przetwarzaniu, co może prowadzić do [przekroczeń limitu czasu w Overleaf](/latex/pl/baza-wiedzy/038-fixing-and-preventing-compile-timeouts.md).
* obsługa tych czcionek przez LuaLaTeX może być [uznana za eksperymentalną](https://github.com/latex3/luaotfload/issues/96#issuecomment-530317399): wyniki mogą się różnić w zależności od wersji TeX Live użytej w twoim projekcie; dlatego zaleca się eksperymentowanie i zachowanie ostrożności.

**Przetwarzanie danych glifów SVG**

SVG umożliwia projektantom tworzenie złożonych i kolorowych projektów przedstawiających glify czcionki — z zastrzeżeniem pewnych ograniczeń SVG [udokumentowanych w specyfikacji OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/svg). Jednak silniki TeX, w tym LuaHBTeX, nie mogą bezpośrednio importować (używać) plików ani danych SVG — takich jak dane SVG używane do opisu kształtów glifów w kolorowych czcionkach OpenType w odmianie SVG. Dane SVG glifu muszą zostać przekonwertowane do formatu PDF, ponieważ LuaHBTeX może go użyć do złożenia glifu i wygenerowania końcowego dokumentu PDF. Ta konwersja SVG do PDF jest obsługiwana przez kod Lua w `luaoftload`: dane SVG każdego glifu są wyodrębniane z pliku czcionki, zapisywane do tymczasowego `.svg` pliku i konwertowane do PDF za pomocą Inkscape z poziomu wiersza poleceń. Wyodrębnianie danych SVG i konwertowanie ich do PDF wiąże się z pewnym narzutem przetwarzania, co może skutkować potencjalnie długim czasem kompilacji dokumentu — szczególnie w przypadku dokumentów używających dużych czcionek SVG zawierających tysiące glifów emoji.

#### Rastrowe kolorowe czcionki OpenType

**Używanie formatu kolorowych czcionek OpenType CBDT/CBLC Google z LuaHBTeX**

[Noto Color Emoji](https://fonts.google.com/noto/specimen/Noto+Color+Emoji) jest kolorową czcionką OpenType dołączoną do TeX Live, co ułatwia jej użycie w projekcie Overleaf. Ponieważ Noto Color Emoji używa grafiki w formacie PNG do reprezentowania glifów emoji, możemy jej użyć do złożenia dużego (rastrowego) emoji kaczki — jak pokazuje poniższy przykład. Zauważ ponownie, że `fontspec` deklaracja czcionki (`\emojifont`) używa `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}
```

[Otwórz ten przykład LuaLaTeX, aby złożyć rastrową kaczkę.](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)

Oto rastrowa kaczka wygenerowana przez powyższy przykład:

![Rastrowe emoji kaczki złożone przez LaTeX](/files/7131f6678fa182c1f2f253fda441e312dc3b9639)

Jeśli spróbujesz użyć `NotoColorEmoji.ttf` ale pominiesz `[Renderer=Harfbuzz]` z `fontspec` deklarację, LuaHBTeX zakończy się niepowodzeniem i wyświetli komunikat błędu, gdy spróbuje zapisać plik PDF:

```latex
! błąd:  (plik /usr/local/texlive/2020/texmf-dist/fonts/truetype/google/noto-em
oji/NotoColorEmoji.ttf) (ttf): nie znaleziono tabeli loca
```

Przyczyna tego błędu w [tabeli loca](https://docs.microsoft.com/en-us/typography/opentype/spec/loca) to [wyjaśniona na GitHubie](https://github.com/latex3/luaotfload/issues/98#issuecomment-531610153).

**Używanie formatu kolorowych czcionek OpenType sbix firmy Apple z LuaHBTeX**

Testy offline pokazują, że LuaHBTeX obsługuje `sbix` wariant kolorowych czcionek OpenType, ale w chwili pisania tego artykułu nie udało nam się znaleźć odpowiednio licencjonowanej `sbix`-wariantowej kolorowej czcionki emoji, aby zademonstrować składanie kaczki. Prosimy [skontaktować się z nami](https://www.overleaf.com/contact) jeśli znasz taką czcionkę, a my szybko zaktualizujemy ten artykuł, aby jej użyć.

## Wprowadzenie do API HarfBuzz w LuaHBTeX

![Db.gif](/files/93b812426c24c328250d9ffa560d58bb7ed64a44) ![Db.gif](/files/93b812426c24c328250d9ffa560d58bb7ed64a44)

Składanie tekstu, zwłaszcza w językach o złożonych systemach pisma, a nawet emoji, jest z natury trudnym zadaniem, więc nie dziwi, że HarfBuzz jest zaawansowaną biblioteką, z którą może być trudno pracować — chyba że jesteś już zaznajomiony z operacjami składania tekstu. W tej końcowej sekcji przyglądamy się integracji HarfBuzz w LuaHBTeX i temu, jak uzyskać do niej dostęp za pomocą kodu Lua w `\directlua`.

Nasz przykład używa dość prostego kodu, aby zademonstrować API HarfBuzz w LuaHBTeX. Jest on nieco sztuczny, nie ma jakości produkcyjnej ani nie jest zbyt praktyczny, ponieważ jego jedynym celem jest wprowadzenie kilku podstawowych idei. Podzieliliśmy kod Lua na dwa `\directlua` fragmenty: pierwszy ładuje `luaharfbuzz` bibliotekę i tworzy pewne zmienne globalne, których użyjemy w naszym drugim `\directlua` fragmencie, gdzie definiujemy makro o nazwie `\codestoemoji`.

Wydaje się stosowne odtworzyć użycie przez Knutha podwójnych znaków niebezpiecznego zakrętu (obraz dzięki uprzejmości [tej strony](http://www.truetex.com/db.htm)) ponieważ treść jest nieco niskopoziomowa i „zagląda pod maskę” — choć mamy nadzieję, że może zainteresować bardziej śmiałego czytelnika. Integracja HarfBuzz w LuaHBTeX wywodzi się z projektu [luaharfbuzz na GitHubie](https://github.com/ufyTeX/luaharfbuzz/wiki#projects-using-luaharfbuzz) gdzie można znaleźć [wprowadzenie do projektu](https://github.com/ufyTeX/luaharfbuzz/wiki) wraz z [listą API luaharfbuzz](http://ufytex.github.io/luaharfbuzz/).

### Pierwsze kroki: załaduj bibliotekę luaharfbuzz i znajdź czcionkę

Aby użyć API HarfBuzz w LuaHBTeX, najpierw musimy załadować bibliotekę (moduł) o nazwie `luaharfbuzz`, wbudowany w LuaHBTeX, i zapisać zwróconą tabelę w (globalnej) zmiennej, którą nazwiemy `hblib`:

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

Następnie musimy zlokalizować odpowiednią kolorową czcionkę emoji OpenType: użyjemy Noto Color Emoji — zauważ, że jesteśmy bardzo leniwi i nie sprawdzamy błędów na wypadek, gdybyśmy jej nie znaleźli! Aby ją znaleźć, użyjemy `kpse` biblioteki (Kpathsea), która również jest częścią LuaTeX/LuaHBTeX:

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

Teraz, gdy mamy dostęp do biblioteki HarfBuzz za pośrednictwem naszej zmiennej `hblib`, oraz ścieżkę do odpowiedniej czcionki (`pathtofontfile`), możemy zacząć używać `hblib`. Na początek utworzymy czcionkę HarfBuzz i obiekt HarfBuzz face do użycia w drugim `\directlua` fragmencie kodu, gdzie definiujemy nasze makro.

```latex
%Utwórz obiekt HarfBuzz face i czcionkę HarfBuzz z Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)
```

#### Czcionka HarfBuzz i obiekt HarfBuzz face: czym są?

Skopiowany [Obiekt HarfBuzz face](https://harfbuzz.github.io/fonts-and-faces.html) reprezentuje kroj pisma wczytany z pliku czcionki, ale bez ustawionych konkretnych parametrów (takich jak rozmiar). [Obiekt czcionki HarfBuzz](https://harfbuzz.github.io/fonts-and-faces.html) reprezentuje *konkretną instancję* obiektu HarfBuzz face; w konsekwencji z jednego obiektu HarfBuzz face można wyprowadzić różne obiekty czcionki HarfBuzz: każdej czcionce HarfBuzz można nadać inne wartości właściwości, takich jak rozmiar. Obiekt HarfBuzz face jest wyższym poziomem abstrakcji niż obiekt czcionki HarfBuzz.

### Używanie glifów czcionki do tworzenia plików PNG

Ostatnia część naszego pierwszego `\directlua` fragmentu to funkcja o nazwie `writePNGglyph(hbfontobject, glyphID)` której używamy, aby pokazać, że niektóre kolorowe czcionki OpenType, takie jak Noto Color Emoji, używają grafiki PNG do reprezentowania zawartych w nich glifów emoji.

Ta funkcja używa API HarfBuzz w LuaHBTeX do wyodrębniania danych PNG z glifów i zapisywania tych danych do `.png` plik o nazwie `Graphics<glyphID>.png`. Nazwa tego `.png` pliku jest zwracana do użycia przez `\includegraphics` do osadzania obrazów glifów PNG w naszym składanym pliku PDF.

Z `writePNGglyph(hbfontobject, glyphID)` na miejscu, nasz pierwszy `\directlua` fragment kodu wygląda tak:

```latex
\directlua{

% Załaduj bibliotekę luaharfbuzz z LuaHBTeX
hblib=require("luaharfbuzz")

% Zlokalizuj czcionkę Noto Color Emoji na serwerze Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Utwórz obiekt HarfBuzz face i czcionkę HarfBuzz z Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% Ta funkcja przyjmuje czcionkę i identyfikator glifu:
% wyodrębnia dane PNG glifów i zapisuje
% je do pliku .png

function writePNGglyph(hbfontobject, glyphID)

    % Pobierz dane PNG glifu
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % Utwórz nazwę pliku dla naszego pliku .png
    local fname="Glyph"..glyphID..".png"

    % Zapisz plik .png i zwróć nazwę pliku
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % Zwróć nazwę pliku do użycia przez \includegraphics
    return fname
end
}
```

### Drugi fragment \directlua: utwórz makro \codestoemoji

Celem jest zdefiniowanie makra `\codestoemoji` które możemy wywołać z fragmentem tekstu zawierającym kody znaków emoji, które chcemy poddać kształtowaniu przez HarfBuzz. Konkretnie użyjemy `\Uchar<kod znaku>` do reprezentowania każdego znaku emoji; na przykład:

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

W definicji `\codestoemoji` dzieje się bardzo wiele, co wyjaśnimy poniżej, ale definicja wygląda tak:

```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()
    %Tabela glifów, hbglyphs, ma indeksowanie od 1
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        %Zmniejsz rozmiar importowanych obrazów PNG
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}
```

#### Zrozumienie definicji makra \codestoemoji

Ta `\codestoemoji` makro to głównie kod Lua zawarty w `\directlua`, więc jeśli chcesz dowiedzieć się więcej o tym, jak *jak* `\directlua` działa, sprawdź artykuł w Overleaf [Zrozumienie `\directlua`](/latex/pl/artykuly-szczegolowe/09-an-introduction-to-luatex-part-2-understanding-directlua.md). Wyjaśnia, jak LuaTeX i LuaHBTeX przetwarzają `\directlua` gdy w kodzie Lua są zawarte polecenia TeX/LaTeX, a w szczególności potrzebę użycia `\noexpand` i `\unexpanded`.

**Radzenie sobie z parametrem makra: "#1"**

Makro zaczyna się od tych trzech linii:

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

które wykonują następujące zadania:

* `local str="#1"`: tworzy łańcuch Lua z wejścia przekazanego przez makro;
* `local hbbuffer = hblib.Buffer.new()`: używa API HarfBuzz do utworzenia bufora, który będzie przechowywał tekst, który chcemy poddać kształtowaniu przez HarfBuzz;
* `hbbuffer:add_utf8(str)`: dodaje łańcuch w formacie UTF-8, utworzony z danych wejściowych naszego makra, do bufora HarfBuzz.

Pierwsza linia kodu

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

wydaje się dość prosta, ale jej działanie wiąże się ze sporą złożonością, którą warto nieco dokładniej zbadać.

Jeśli weźmiemy pod uwagę trzecią linię kodu

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

widzimy, że używa naszej `zmiennej str` aby dostarczyć buforowi HarfBuzz łańcuch Unicode sformatowany w UTF-8. Aby to działało, zmienna `zmiennej str` musi sama zawierać tekst Unicode sformatowany jako UTF-8; pojawia się więc pytanie: *jak* czy LuaHBTeX „przekonwertował” argument makra `"#1"`, zawierający `\Uchar` polecenia, do zmiennej łańcuchowej Lua `zmiennej str` zawierającej tekst UTF-8 dla HarfBuzz?

Jeśli spojrzymy na zamierzone użycie `\codestoemoji` makra:

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

dane wejściowe, takie jak `\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065...`, wcale nie przypomina sekwencji znaków emoji zakodowanych w UTF-8. Co więcej, HarfBuzz nic nie wie o poleceniach TeX. W jakiś sposób surowe wejście TeX składające się z `\Uchar` poleceń jest przekształcane w znaki Unicode zakodowane w UTF-8, których HarfBuzz może użyć, ale *jak*?

Odpowiedź tkwi w zachowaniu `\Uchar` polecenia: próba wywołania `\codestoemoji` używając `\char` zamiast `\Uchar` zakończy się niepowodzeniem, ale *dlaczego*?

**\Uchar: rozwinięcie w \directlua**

Gdy `\codestoemoji` makro jest wywoływane, `\directlua` polecenie, zapisane w definicji makra, musi przygotować kod Lua do wysłania do wbudowanego interpretera Lua w LuaHBTeX. Częścią tego procesu przygotowywania kodu jest rozwinięcie wszelkich poleceń TeX/LaTeX obecnych w oryginalnym kodzie Lua w definicji makra, wraz z rozwinięciem wszelkich argumentów makra podanych przez użytkownika. Ten proces rozwinięcia daje listę tokenów, która następnie jest konwertowana z powrotem na tekst, tworząc kod Lua przekazywany do interpretera Lua. Dla wygody odtwarzamy diagram z artykułu w Overleaf [Zrozumienie `\directlua`](/latex/pl/artykuly-szczegolowe/09-an-introduction-to-luatex-part-2-understanding-directlua.md):

![Mechanika \directlua](/files/4276c0e177453214a7b2d5abd340faad40e72e0a)

Makro `\codestoemoji` ma być wywoływane za pomocą `\Uchar` poleceń i, [jak wspomniano wcześniej w artykule](#the-key-difference-expansion), `\Uchar` jest poleceniem rozwijalnym, którego rozwinięcie generuje token znaku. W ramach operacji przetwarzania `\directlua`, LuaHBTeX rozwija każde `\Uchar<kod znaku>` polecenie tam, gdzie *usuwa* każdy `\Uchar<kod znaku>` usuwane z wejścia i *zastępuje* zastępuje je odpowiednią wartością rozwinięcia: tokenem znaku reprezentującym `<kodu znaku>`.

W końcowym etapie przetwarzania początkowa lista tokenów wygenerowana przez `\directlua` jest konwertowana *z powrotem na tekst* aby stać się kodem Lua przeznaczonym dla interpretera Lua (patrz diagram powyżej). Wszystkie tokeny znaków utworzone przez rozwinięcie `\Uchar` są również *konwertowane z powrotem na tekst*: ta konwersja tokenów znaków na tekst generuje reprezentacje UTF-8 oryginalnych `<kodu znaku>` wartości.

W naszym przykładzie, zanim kod Lua zostanie wygenerowany i będzie gotowy dla interpretera Lua, dane wejściowe makra dla "#1" zostały przekształcone w sekwencję tekstu UTF-8: `zmiennej str` zmienna jest teraz ciągiem tekstowym UTF-8, który można bezpiecznie dodać do bufora HarfBuzz.

**Dlaczego \char nie działa?**

Krótka odpowiedź brzmi: ponieważ `\char` to *nie* komenda rozwijalna. W przeciwieństwie do `\Uchar` komend, `\char` polecenia *nie są usuwane* z danych wejściowych podczas `\directlua`wstępnego przetwarzania, aby wygenerować listę tokenów, przechodzą one „na wylot”, by zostać włączone do listy tokenów tworzonej przez `\directlua`. Na przykład, jeśli argumentem do `\codestoemoji` zawierał `\char"1F3F4` LuaHBTeX przekonwertowałby to na sekwencję tokenów i zapisał je jako część całkowitej generowanej listy tokenów.

W następnym etapie przetwarzania, podczas konwertowania tokenów z powrotem na tekst, wynikowy kod Lua zawierałby *literał tekstowy* `\char"1F3F4` w tekście użytym do zdefiniowania naszej zmiennej `zmiennej str`. Gdy zawartość `zmiennej str` zostanie dodana do bufora HarfBuzz, nie będzie zawierać sekwencji zakodowanej w UTF-8 reprezentującej znak emoji „1F3F4, lecz będzie zawierać literał tekstowy `\char"1F3F4`, którą HarfBuzz spróbuje poddać kształtowaniu i, w naszym przypadku, nie wygeneruje glifu emoji. Nawiasem mówiąc, ciąg `\char"1F3F4` również powodowałby błędy składni Lua, chyba że zostałby utworzony jako „łańcuch z długimi nawiasami” — zobacz [Czym są sekwencje escape Lua](/latex/pl/artykuly-szczegolowe/09-an-introduction-to-luatex-part-2-understanding-directlua.md#what-are-e2809clua-escape-sequencese2809d3f) dla kontekstu na temat tego problemu.

Jeśli spróbujemy użyć `\codestoemoji` przez `\char` komendy, tak jak tutaj:

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

LuaHBTeX zakończy się niepowodzeniem i zgłosi błąd składni mniej więcej taki:

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

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

Interpretator Lua napotkał problem, więc
pozostała część tego fragmentu Lua zostanie zignorowana.
```

#### Wywołanie funkcji kształtowania HarfBuzz

**Ustawianie parametrów bufora**

HarfBuzz czasami wymaga dodatkowych informacji o tekście, który ma zostać poddany kształtowaniu. Możesz podać te informacje, konfigurując swój `<buffer variable>` używając *metody bufora*, takie jak:

* `<buffer variable>:set_direction(*HarfBuzz direction*)`;
* `<buffer variable>:set_language(*HarfBuzz language*)`;
* `<buffer variable>:set_script(*HarfBuzz script*)`.

Na przykład musimy poinformować HarfBuzz, że kierunek naszego tekstu emoji będzie od lewej do prawej. W tym celu używamy `set_direction()` metody na naszym `<buffer variable>` (zwanym `hbbuffer`) zapisując:

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

gdzie `hblib.Direction.new("ltr")` tworzy „obiekt kierunku” odpowiedni do przekazania do silnika HarfBuzz za pośrednictwem Lua.

**Wykonanie kształtowania**

Gdy bufor zostanie odpowiednio zainicjalizowany, możemy poprosić HarfBuzz o wykonanie właściwego kształtowania za pomocą funkcji `shape_full()`. W naszym przykładzie piszemy:

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

3\. i 4. parametr `shape_full()` funkcji muszą być tabelami Lua — użyliśmy pustych tabel „`{}`” dla obu parametrów. Ogólna postać `shape_full()` jest:

```latex
shape_full(czcionka HarfBuzz, bufor HarfBuzz, {cechy czcionki}, {"shaper"}
```

* **`{"shaper"}`**: Zwykle nie trzeba tego ustawiać, ale opcje to `{"ot"}` lub `{"graphite2"}`. Więcej informacji o pojęciu „shaper” można znaleźć w [dokumentacji HarfBuzz](https://harfbuzz.github.io/shaping-and-shape-plans.html)—zwróć uwagę, że dokumentuje ona niskopoziomowe API C, a nie oparty na Lua `luaharfbuzz` binding (implementację).
* **`{font features}`**: To jest tabela zawierająca [funkcje OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist)—obsługiwane przez czcionkę— które chcesz, aby HarfBuzz zastosował podczas kształtowania.

Każda cecha czcionki, której chcesz użyć, musi zostać utworzona za pomocą `luaharfbuzz` funkcji bibliotecznej

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

gdzie

* `library_instance` to twoja `luaharfbuzz` zmienna instancji biblioteki (`hblib` w naszym przykładzie);
* `feature_string` używa [składni do definiowania cech](https://github.com/ufytex/luaharfbuzz/wiki/Feature-Strings). Przykładami są `+smcp` aby włączyć wersaliki lub `-kern` aby wyłączyć kerning.

Na przykład:

```latex
local dosmcp = hblib.Feature.new("+smcp")
local nokern = hblib.Feature.new("-kern")
% Użyj swoich cech czcionki w ten sposób
local res = hblib.shape_full(hbfont, hbbuffer, {dosmcp,nokern},{})
```

#### Dostęp do wyniku: pobieranie glifów

I na koniec, jeśli operacja kształtowania zakończy się powodzeniem, ukształtowane glify zostaną zwrócone w zmiennej bufora `hbbuffer` utworzonej wcześniej w kodzie.

Uzyskujemy dostęp do glifów za pomocą metody bufora `get_glyphs()` i używamy pętli, aby pobrać każdy pojedynczy glif. Zauważ, że tabela Lua przechowująca glify, `hbglyphs` w naszym przykładzie, jest indeksowana od 1, a nie od 0.

Każdy glif ma *identyfikator glifu* (co mylące, nazywany `codepoint`), a czcionka HarfBuzz (`hbfont`) jest przekazywana do `writePNGglyph()` funkcji, która tworzy plik PNG, wykorzystując rastrową reprezentację tego glifu przez czcionkę.

`writePNGglyph()` zapisuje plik PNG i zwraca nazwę pliku PNG, która służy do zaimportowania (przeskalowanego) pliku PNG do naszego dokumentu LaTeX za pomocą `\includegraphics[scale=0.75]{<fname>}`. Zauważ, jak możemy użyć `\includegraphics` bezpośrednio w kodzie Lua.

```latex
if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    %Tabela glifów, hbglyphs, ma indeksowanie od 1
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        %Zmniejsz rozmiar importowanych obrazów PNG
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
```

### Pełny kod, który możesz otworzyć w Overleaf

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

% Załaduj bibliotekę luaharfbuzz z LuaHBTeX
hblib=require("luaharfbuzz")

% Znajdź czcionkę Noto Color Emoji na serwerze Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Utwórz obiekt HarfBuzz face i czcionkę HarfBuzz z Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% Ta funkcja przyjmuje czcionkę i identyfikator glifu:
% wyodrębnia dane PNG glifów i zapisuje
% je do pliku .png

function writePNGglyph(hbfontobject, glyphID)

    % Pobierz dane PNG glifu
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % Utwórz nazwę pliku dla naszego pliku .png
    local fname="Glyph"..glyphID..".png"

    % Zapisz plik .png i zwróć nazwę pliku
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % Zwróć nazwę pliku do użycia przez \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()
    % Tabela glifów, hbglyphs, jest indeksowana od 1.
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        %Zmniejsz rozmiar importowanych obrazów PNG
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}

Kaczka: \codestoemoji{\Uchar"1F986}

Flaga: \codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
\end{document}
```

[Otwórz ten przykład API luaharfbuzz w Overleaf.](/latex/pl/artykuly-szczegolowe/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md)

Ten przykład generuje następujący wynik:

![Harfbuzzexample.png](/files/49f85d399df0e607faba563de544d5ab5b17483c)

## Sekcja bonusowa: Zabawa z matematyką emoji

Na lekką nutę, członek zespołu Overleaf użył [`emoji` pakiet LaTeX](https://ctan.org/pkg/emoji?lang=en) do stworzenia zabawnego przykładu:

```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}
```

[Otwórz ten zabawny przykład w 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)

Ten przykład generuje następujący wynik:

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


---

# 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/pl/artykuly-szczegolowe/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.
