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

# Een overzicht van technologieën die het gebruik van kleur-emoji-lettertypen in LaTeX ondersteunen

## Inleiding

Dit artikel biedt een overzicht van verschillende [achtergrondonderwerpen](#which-topics-do-we-cover) met betrekking tot het gebruik van OpenType-kleurfonts voor het zetten van kleurrijke emoji in LaTeX. We hebben geprobeerd een breed scala aan materiaal aan te bieden, afgestemd op een breed spectrum aan interesses en expertise. Om het artikel beheersbaar te houden, laten we in onze behandeling van bepaalde onderwerpen veel technische details weg, maar we hopen dat er voldoende materiaal is om je op weg te helpen bij het verkennen van het zetten van kleurrijke emoji in LaTeX.

**Update (juli 2023)**: Dit artikel werd voor het eerst gepubliceerd in augustus 2021 en herzien in juli 2023 om de sectie over [Het gebruik van op SVG gebaseerde OpenType-kleurfonts met LuaHBTeX](#using-svg-based-opentype-color-fonts-with-luahbtex).

### Welke onderwerpen behandelen we?

Dit artikel behandelt de volgende algemene onderwerpen:

* Unicode: de standaard die emoji als tekens codeert en hun verwachte gedrag in tekstverwerking en zetapplicaties vastlegt.
* OpenType-kleurfonts: gespecialiseerde fonts die kleurrijke weergaven bieden van emoji-tekens die in je LaTeX-document worden weergegeven.
* Tekstvormgeving: een sleutelcomponent introduceren bij het zetten van talen met complexe scripts en emoji.
* HarfBuzz: de component van LuaHBTeX die geavanceerd meertalige zetwerk en het gebruik van OpenType-kleurfonts mogelijk maakt om emoji in LaTeX te zetten.
* Verschillende TeX-engines: hun ondersteuning voor OpenType-kleurfonts verkennen en selecteren welke TeX-engine je wilt gebruiken.
* LuaHBTeX’s HarfBuzz-API: een introductie tot de “magie” achter [tekstvormgeving](#the-concept-of-text-shaping) in LuaHBTeX.

### Drie manieren om kleurrijke emoji te zetten

Kleurrijke emoji kunnen met LaTeX op drie hoofdmanieren worden gezet:

1. Gebruikmaken van standaard LaTeX-gereedschappen voor grafische weergave zoals TikZ, MetaPost of Asymptote om de emoji te tekenen.
2. Emoji invoegen met vooraf gemaakte emoji-afbeeldingen die in externe bestanden zijn opgeslagen.
3. Emoji behandelen als Unicode-gecodeerde tekst en [tekstvormgeving](#the-concept-of-text-shaping) meestal [OpenType-kleurfonts](#opentype-color-fonts) gebruiken om ze te zetten.

De praktische opties voor het opnemen van kleurrijke emoji in je LaTeX-document hangen af van de TeX-engine die wordt gebruikt om dat document te compileren: dat wil zeggen, of je gebruikt:

* pdfLaTeX: pdfTeX-engine + LaTeX;
* XeLaTeX: XeTeX-engine + LaTeX;
* LuaLaTeX: LuaHBTeX-engine (vanaf TeX Live 2020) + LaTeX.

Al deze drie TeX-engines kunnen LaTeX-gereedschappen of -pakketten gebruiken om emoji te tekenen of `\includegraphics{...}` te gebruiken om emoji in externe grafische bestanden in te voegen. Grafieken tekenen of importeren zijn ideale technieken om emoji te zetten wanneer je een oplossing nodig hebt die niet afhangt van de TeX-engine die wordt gebruikt om het LaTeX-document te compileren.

Als je werkstroom echter de flexibiliteit biedt om een bepaalde TeX-engine te kiezen, en je liever OpenType-kleurfonts en op Unicode gebaseerde tekstverwerking gebruikt, dan heb je de nieuwste versie van LuaTeX, LuaHBTeX genaamd, nodig. Vanaf TeX Live 2020 wordt LuaHBTeX gebruikt om LaTeX-documenten te compileren op basis van de LuaLaTeX-indeling.

## Achtergrond over Unicode en emoji-tekens

### Tekenencoderingen

Computers slaan tekst op, verzenden en verwerken tekst met behulp van een reeks numerieke (gehele) waarden die de *tekens* van die tekst vertegenwoordigen. Betrouwbare tekstverwerking vereist dat producenten en consumenten van tekst het eens zijn over welke gehele waarden gebruikt moeten worden om afzonderlijke tekens binnen de tekststroom weer te geven. Met andere woorden: wat is de *teken* *codering?* Een codering is de verzameling overeengekomen gehele waarden die zijn toegewezen om een bepaalde set tekens weer te geven: elk teken wordt vertegenwoordigd door een gehele waarde binnen de gebruikte codering.

### Maak kennis met Unicode

Historisch gezien, in het tijdperk van 8-bit tekst, werden veel verschillende tekenencoderingen gebruikt, waarbij steeds de dreiging opduikte van *coderingsovereenkomsten die niet overeenkomen* : producenten en consumenten van tekst veronderstellen ten onrechte verschillende coderingen, wat resulteert in fouten bij de tekstverwerking. Iedereen die al enkele jaren met TeX/LaTeX heeft gewerkt, is waarschijnlijk coderingsovereenkomsten die niet overeenkomen tegengekomen tussen de invoertekst en de fonts die worden gebruikt om een document te zetten. Als de documentfonts zijn geconfigureerd om een andere codering te gebruiken dan die van de tekst, leidt dit waarschijnlijk tot ontbrekende of foutieve tekens in de gezette PDF.

Deze historische coderingsproblemen kunnen worden opgelost met behulp van een internationale standaard die alle tekens van de wereld codeert: Unicode. De Unicode-standaard is niet statisch, maar wordt periodiek bijgewerkt om extra tekens en scripts (schrijfsystemen) in zijn coderingsschema op te nemen. Er is een [formeel beoordelingsproces voor het voorstellen van nieuwe tekens](http://www.unicode.org/pending/proposals.html) met een specifiek [schema voor nieuwe emoji-tekens](https://www.unicode.org/emoji/proposals.html).

### Hoeveel Unicode-tekens?

Unicode codeert een theoretisch maximum van 1.114.112 tekens. Elk van de 1.114.112 gehele waarden wordt een *codepunt*genoemd: de gehele waarde die wordt toegewezen om elk teken te identificeren. Om verschillende technische redenen kunnen echter slechts [1.112.064 codepunten](https://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology) worden toegewezen aan daadwerkelijke tekens: 2048 codepunten zijn niet-toewijsbaar en verboden voor gebruik binnen Unicode-conforme tekst.

Ten tijde van het schrijven (de eerste versie van dit artikel) had versie 13 van de Unicode-standaard in totaal 143.859 codepunten toegewezen aan daadwerkelijke tekens, waaronder [3304 tekens die nu als emoji zijn gecodeerd](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (zie pagina 2 van dat document). De groei in het aantal tekens dat door Unicode wordt gecodeerd, wordt mooi gedocumenteerd in het artikel [Hoeveel Unicode-tekens zijn er?](https://www.babelstone.co.uk/Unicode/HowMany.html) en in een [Wikipedia-item](https://en.wikipedia.org/wiki/Unicode#Versions).

### Unicode-vlakken

De volledige verzameling van 1.114.112 Unicode-codepunten is gegroepeerd in 17 zogenaamde vlakken: Vlak 0 tot en met Vlak 16, elk met 65536 codepuntwaarden, wat neerkomt op een totaal van $$17\times2^{16} = 1,114,112$$ tekens. Vlak 0, het [Basic Multilingual Plane](https://en.wikipedia.org/wiki/Plane_\(Unicode\)#Basic_Multilingual_Plane)genoemd, codeert de meest gebruikte tekens. Vlakken 1–16 worden [Supplementary Planes](http://unicode.org/glossary/#supplementary_planes).

### De opkomst van emoji

Nieuwe tekens ontstaan door veranderende vormen van menselijke communicatie, en mobiele telefoontechnologie leidde tot zo’n set tekens: emoji, die zich in Japan ontwikkelden tijdens de late jaren negentig. Het is niet verwonderlijk dat de [Unicode-FAQ over Emoji](https://unicode.org/faq/emoji_dingbats.html) opmerkt

> “Het woord emoji komt van het Japanse [絵](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E7%B5%B5) (e ≅ afbeelding) + [文字](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E6%96%87) (moji ≅ geschreven teken).”

Lezers die geïnteresseerd zijn in de achtergrond en historische ontwikkeling van emoji, vinden misschien interesse in deze [Unicode-inleiding](https://unicode.org/reports/tr51/#Introduction) of het artikel [I second that emoji: De standaarden, structuren en sociale productie van emoji](https://firstmonday.org/ojs/index.php/fm/article/view/9381).

Pas in 2010, met de release van [versie 6.0 van de Unicode-standaard](https://www.unicode.org/versions/Unicode6.0.0/)werden veel emoji formeel erkend als *tekens* op zichzelf staand. Unicode 13.0 codeerde [3304 tekens als emoji](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (zie pagina 2 van dat document), terwijl Unicode 13.1 [3521 emoji vermeldt](https://unicode.org/emoji/charts/emoji-counts.html).

### Emoji leven op een hoger vlak

Unicode heeft veel emoji-tekens toegewezen aan codepunten buiten het Basic Multilingual Plane (BMP), gecodeerd [in Vlak 1](https://en.wikibooks.org/wiki/Unicode/Character_reference/1F000-1FFFF) met codepunten in het bereik 1F000–1FFFF—wat een belangrijk gevolg heeft voor iedereen die emoji-tekens wil *kopiëren en plakken* in de Overleaf-editors (Code Editor of Visual Editor). De teksteditors van Overleaf kunnen alleen tekens binnen het Basic Multilingual Plane verwerken, hoewel we hopen dat toekomstige upgrades ondersteuning voor niet-BMP-tekens zullen introduceren. Merk op dat deze beperking alleen van invloed is op niet-BMP-tekens binnen tekst die in bestanden wordt geplakt die via de Overleaf-editors moeten worden bewerkt. Er zijn andere manieren om toegang te krijgen tot emoji-tekens:

* Gebruik van de primitieve opdrachten `\char"<codepunt>` of `\Uchar"<codepunt>` (zie [dit gedeelte](#optional-detail-luatexluahbtex-char-vs-uchar) van het artikel).
* Gebruik van invoertekstbestanden die emoji-tekens bevatten in UTF-8-formaat.
* Gebruik van LaTeX-opdrachten (macro’s) die emoji-tekens invoegen.

#### Emoji en andere niet-BMP-tekens plakken in Overleaf

Als je een emoji-teken plakt, bijvoorbeeld 😀, in de Overleaf Code Editor, wordt dit momenteel omgezet in de tekens ��.

![Fout door niet-BMP-tekens te kopiëren en plakken in Overleaf-editors](/files/5aa6114face2fbd90641d3e661e5124def11d196)

Het teken � heeft Unicode-codepunt FFFD en de officiële naam is het REPLACEMENT CHARACTER en wordt gebruikt om “[een onbekend, niet-herkend of onverteerbaar teken te vervangen](https://en.wikipedia.org/wiki/Specials_\(Unicode_block\))”.

### Unicode-codepunten (U+) gebruiken in LuaLaTeX

De Unicode-documentatie stelt codepuntwaarden voor met de notatie `U+<hexadecimale waarde>`— zoals `U+1F600`, waarbij `1F600` is de `<hexadecimale waarde>` van het Unicode-codepunt voor het 😀-emoji-teken. Om deze codepuntwaarden in LuaLaTeX te gebruiken, verwijder je de `U+` en schrijf je `\char"<hexadecimale waarde>` of `\Uchar"<hexadecimale waarde>`zijn gegenereerd. Het `"` karakter vertelt een TeX-engine dat het opgegeven getal in hexadecimaal is. Om bijvoorbeeld de 😀-emoji te gebruiken, zou je schrijven `\char"1F600` of `\Uchar"1F600`—met gebruik van een font dat het kan zetten.

Een minimaal LuaLaTeX-voorbeeld met `\char` en `\Uchar` om het 😀-emoji-teken te zetten kan er als volgt uitzien:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz]{NotoColorEmoji.ttf}
%Gebruik \emojifont binnen een groep om de effecten lokaal te houden
{\emojifont
\Uchar"1F600
\char"1F600}
\end{document}
```

[Open dit LuaLaTeX-voorbeeld in 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)

**(optioneel detail) LuaTeX/LuaHBTeX: \char versus \Uchar**

Naast de conventionele `\char<tekencode>` opdracht om een specifieke `<tekencode>`te zetten, met het huidige font, bieden de LuaTeX-, LuaHBTeX- en XeTeX-engines ook de `\Uchar<tekencode>` opdracht. Vanuit het perspectief van een gebruiker zien de resultaten van `\char` en `\Uchar` er hetzelfde uit, maar er is een subtiel verschil in hoe deze opdrachten werken, zoals we hieronder opmerken.

**Het belangrijkste verschil: expansie**

`\Uchar` is een zogenaamde [expandeerbare opdracht](/latex/nl/diepgaande-artikelen/22-how-does-expandafter-work-the-meaning-of-expansion.md#expansion-a-general-term-for-a-set-of-operations) terwijl `\char` dat niet is. Wanneer een `\char<tekencode>` of `\Uchar<tekencode>` opdracht wordt “uitgevoerd”—d.w\.z. de opdracht wordt niet opgeslagen als onderdeel van een macro of andere tokenlijst—vinden de volgende acties plaats binnen de TeX-engine:

* **`\char<tekencode>`** instrueert de TeX-engine om onmiddellijk een tekentoken in te voegen, dat `<tekencode>`vertegenwoordigt, in welk stuk inhoud hij op dat moment ook aan het zetten is.
* Daarentegen heeft **`\Uchar<tekencode>`** twee verschillende verwerkingsstappen:

1. De `\Uchar<tekencode>` opdracht wordt *uitgebreid*en de `<tekencode>` wordt omgezet in een tijdelijke tokenlijst die één enkel [tekentoken](/latex/nl/diepgaande-artikelen/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#tex-tokens-101-28and-notions-of-expansion29) bevat, wat de `<tekencode>`.
2. vertegenwoordigt *beschikbaar gemaakt* voor de TeX-engine als bron van de volgende invoer. In feite “verlegt” de TeX-engine tijdelijk zijn blik om die ene tokenlijst te gebruiken als de locatie van het volgende invoeritem (token). Standaard gaat de TeX-engine gewoon terug om dat token te lezen (invoer) en het overeenkomstige teken te zetten, waarmee het gedrag van de `\char` commando. **Echter**omdat dat `<tekencode>` niet onmiddellijk werd gezet, maar tijdelijk *opgeslagen* (opgeslagen) als één token, kunnen primitieve TeX-opdrachten of LaTeX-macro’s dat token gebruiken (opvangen)—het hoeft niet meteen te worden gezet, maar kan indien nodig worden gebruikt in verdere verwerking.

In feite zegt `\char<tekencode>` “zet dit `<tekencode>` nu,” terwijl `\Uchar<tekencode>` een vorm van “uitgestelde actie” heeft door een opgeslagen tekentoken te creëren en het beschikbaar te maken als het volgende invoeritem (een token). Dat token kan ofwel worden gebruikt (opgevangen) door TeX-opdrachten en macro’s, of opnieuw worden gelezen door de TeX-engine en worden gezet.

### Unicode (codering) vertelt niet het hele verhaal

De mogelijkheid om emoji-tekens te gebruiken binnen Unicode-gecodeerde tekst is slechts een deel van het succesverhaal van emoji. De toename in het gebruik van emoji werd ook mogelijk gemaakt door ontwikkelingen in [OpenType-fonttechnologie](https://learn.microsoft.com/en-us/typography/opentype/)—fonts waarvan de glyphgegevens (tekeningen van tekens) [kleurgegevens](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)kunnen bevatten: zogenaamde [OpenType-kleurfonts](#opentype-color-fonts).

Naast geschikte fonts vereist het gebruik van kleurrijke emoji extra softwarecomponenten waarvan de taken onder meer zijn:

* voorverwerking (“[vormgeven](#the-concept-of-text-shaping)”) van Unicode-gecodeerde tekst, *voorbereiden* voor weergave met een bepaald font;
* *renderen en weergeven* van de kleurrijke emoji *glyphs* op het scherm van een apparaat.

#### Glyph versus teken: zijn ze niet hetzelfde?

De termen “glyph” en “teken” worden vaak gebruikt alsof ze uitwisselbaar zijn—verwijzend naar hetzelfde basisconcept—maar er is een subtiel, zij het belangrijk, verschil in hun betekenis.

Unicode [definieert de term “teken”](http://www.unicode.org/glossary/#character) als:

> “Het kleinste onderdeel van geschreven taal dat semantische waarde heeft; verwijst naar de abstracte betekenis en/of vorm, in plaats van naar een specifieke vorm… ”

Daarentegen is een “glyph” een *specifieke* *vorm* (ontwerp) voor de *visuele weergave* van een bepaald *teken*.

Het teken-versus-glyph-probleem is gemakkelijk waar te nemen wanneer emoji-rijke tekst wordt bekeken op verschillende softwaresystemen/platforms, zoals wanneer je dezelfde tekst leest op je op iOS- of Android gebaseerde mobiele telefoon of Windows-desktopcomputer. Welk apparaat of platform ook wordt gebruikt, de onderliggende tekst (reeks tekens) zou dezelfde Unicode-gecodeerde *emoji* *tekens*bevatten. Het zijn apparaatspecifieke mogelijkheden die betrokken zijn bij *voorverwerking* van die tekst en vervolgens *rendering* en *weergave* van de resultaten, mogelijk met apparaatspecifieke fonts, die verschillende glyphs (tekenontwerpen) opleveren om dezelfde emoji-tekens weer te geven.

Unicode’s [Volledige emoji-lijst](https://unicode.org/emoji/charts/full-emoji-list.html) biedt voorbeeldafbeeldingen die elk Unicode-emoji-teken vertegenwoordigen—en demonstreren de verschillende glyphs die door verschillende technologieleveranciers worden gebruikt. Niet alleen hanteren fontontwerpers hun eigen specifieke ontwerpen (glyphs) om emoji-tekens weer te geven, maar afzonderlijke fonts verschillen ook in het aantal emoji-tekens dat ze ondersteunen (waarvoor ze glyphs bevatten) en kunnen al dan niet de meer geavanceerde functies van emoji-tekstverwerking bevatten die zijn opgenomen in de Unicode-emoji-specificaties.

Het begrip en concept van tekens, hun semantiek en codering, vormen de basis voor de wereld van Unicode: die gaat over tekens. Het ontwerp en de visuele weergave van afzonderlijke tekens, als glyphs, behoren tot fonttechnologieën en het vak van fontontwerp.

#### Unicode-emoji: veel meer dan tekstcodering

De kernrol van Unicode is het bieden van een wereldwijde coderingsstandaard die bepaalt welke gehele waarde, een *codepunt,* moet worden gebruikt om elk teken, inclusief emoji, weer te geven binnen een stroom Unicode-gecodeerde tekst.

De specificatie van Unicode voor emoji definieert ook *verwerkingsgedragingen* voor bepaalde *reeksen* emoji-tekens die binnen een stroom Unicode-gecodeerde tekst voorkomen. Gedefinieerde reeksen emoji-tekens kunnen worden “samengevoegd” via een proces dat [tekstvormgeving](#the-concept-of-text-shaping) wordt genoemd om één resulterende (“samengestelde”) emoji-glyph te produceren—die ene glyph zou door het besturingssysteem van het apparaat worden gebruikt om de oorspronkelijke tekenreeks in de tekst weer te geven.

Het technische rapport van Unicode over [Unicode Emoji](https://unicode.org/reports/tr51/) documenteert de rijke set functies die beschikbaar zijn voor software die Unicode-conforme verwerking van emoji-tekens wil bieden. Als voorbeeld definieert (codeert) Unicode tekens die [emoji-modifiers](http://www.unicode.org/reports/tr51/#Emoji_Modifiers_Table) kunnen worden gebruikt om *variaties* van “basis”-emoji-tekens te genereren, zoals variaties in [huidskleur op basis van de Fitzpatrick-schaal](http://www.unicode.org/reports/tr51/#Diversity). Merk op dat de set basis-emoji-tekens en de toepasselijke modifiers zijn gedefinieerd als onderdeel van de algehele [Unicode-emoji-standaard](http://www.unicode.org/reports/tr51).

De Unicode-pagina [Emoji Sequences](http://unicode.org/emoji/charts/emoji-sequences.html) biedt een overzicht van de reeksen die momenteel door de Unicode-specificatie worden geleverd. Plaats een muisaanwijzer boven een van de emoji-glyphafbeeldingen om een kleine pop-uptooltip te zien die je de onderliggende Unicode-emoji-tekenreeks vertelt die die glyph oplevert:

![EmojiSequenceChart.png](/files/2d928888c77db3f3218460a2c537da88a8fa57f8)

Bijvoorbeeld, de emoji-glyph:

![HandMediumSkinTone.png](/files/56ad521a4600db45212b5d282508afd4821541f5)

staat vermeld in de [sectie met modifiers-sequenties](http://unicode.org/emoji/charts/emoji-sequences.html#modifier_sequences) en wordt geproduceerd door de tweetekensequentie U+1F44B U+1F3FD. Die componenttekens zijn:

U+1F44B:![UnicodeWavingHandDefault.png](/files/abb23711dcac28940f422f2b66ae9571ba8f2d7f) (WAVING HAND)

U+1F3FD:![FitzPatrick3.png](/files/ed80356c427e01af884f380c9ea0122d7ec35f4b) (EMOJI MODIFIER FITZPATRICK TYPE-4)

**Huidskleurmodifiers gebruiken in LuaHBTeX**

Het volgende voorbeeld gebruikt LuaHBTeX om het gebruik van emoji-modifiers te demonstreren:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=HarfBuzz,SizeFeatures={Size=20}]{NotoColorEmoji.ttf}
Geïsoleerde wuivende hand: {\emojifont\Uchar"1F44B}\par
Geïsoleerde modifier: {\emojifont\Uchar"1F3FD}\par
Gecombineerd resultaat: {\emojifont\Uchar"1F44B\Uchar"1F3FD}
\end{document}
```

[Open dit voorbeeld met LuaLaTeX-emoji-modifiers in 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)

Dit voorbeeld levert de volgende uitvoer op:

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

#### UTF-8: zijn rol bij het opslaan van Unicode-tekst

Alle tekst of code die je typt of plakt in de Code Editor van Overleaf (of de Visual Editor) wordt opgeslagen in UTF-8-formaat, dus we bekijken kort wat UTF-8 eigenlijk betekent. UTF staat voor Unicode Transformation Format, en de rol van UTF-8 bij het opslaan of verzenden van Unicode-gecodeerde tekst wordt aangegeven door de frase “Transformation *Format*.”

Unicode’s codepuntwaarden lopen van 0 tot een maximum van 1.114.111, dus het is onmogelijk om alle Unicode-tekenwaarden weer te geven met één 8-bit byte, die slechts tot 256 verschillende waarden kan opslaan: 0 tot en met 255. Het is echter mogelijk om elk Unicode-codepunt als geheel getal weer te geven met een *opeenvolgende reeks* bytegrote waarden—dat is het principe achter UTF-8.

UTF-8 biedt een “recept” om te *transformeren* (d.w\.z. te “coderen” of te “converteren”) een Unicode-geheelwaarde van een codepunt naar een unieke reeks van 1 tot 4 opeenvolgende bytegrote gehele waarden: het aantal opeenvolgende bytes dat nodig is, hangt af van de waarde van het codepunt. Daardoor kun je lezen dat UTF-8 Unicode-tekens opslaat als *meervoudige byte-sequenties* omdat één enkel Unicode-teken (codepuntgeheelwaarde) in UTF-8 wordt weergegeven als een reeks van 1 tot 4 opeenvolgende bytes.

Natuurlijk kan tekst die in UTF-8 is opgeslagen, worden teruggezet naar de oorspronkelijke reeks gehele Unicode-codepuntwaarden—dat is wat XeTeX of LuaTeX/LuaHBTeX moeten doen wanneer ze een LaTeX-invoerbestand lezen dat in UTF-8-formaat is opgeslagen. Die TeX-engines moeten de invoerwaarden van Unicode-codepunten (tekens) kennen voordat ze de tekst kunnen zetten. Merk op dat pdfTeX geen ingebouwde UTF-8-decodering heeft, dus het moet vertrouwen op TeX-macro’s om ingevoerde tekst in UTF-8-formaat te verwerken (decoderen).

**Enkele UTF-8-voorbeelden**

* Het Arabische teken ش (“sjin”) heeft Unicode-codepunt 0634 in hexadecimaal (grondtal 16) of 1588 in decimaal (grondtal 10). In UTF-8 wordt ش weergegeven als 2 (hexadecimale) waarden D8 en B4, dus het teken ش zou worden opgeslagen als de twee opeenvolgende bytes D8B4 binnen UTF-8-gecodeerde tekst.
* Het emoji-teken 😀 heeft Unicode-codepunt 1F600 in hexadecimaal (grondtal 16) of 128512 in decimaal (grondtal 10). In UTF-8 wordt 😀 weergegeven als 4 (hexadecimale) waarden F0, 9F, 98 en 80, dus het teken 😀 zou worden opgeslagen als de 4 opeenvolgende bytes F09F9880 in een UTF-8-tekstbestand.

#### Speciale tekens gebruikt in Unicode-gebaseerde emoji-tekstverwerking

Niet elk teken dat binnen Unicode is gecodeerd, is bedoeld voor visuele weergave via de glyphs in een font: sommige gecodeerde tekens worden aangeduid als *niet-afdrukbare tekens* waarvan het doel is gespecialiseerde tekstverwerkingsfuncties te ondersteunen (binnen ondersteunende software). Verschillende softwaretoepassingen bieden verschillende niveaus van ondersteuning voor de niet-afdrukbare tekens die in Unicode zijn gecodeerd, dus het resultaat hangt af van de softwareomgeving—toepassingen en fonts—die worden gebruikt.

**Twee niet-afdrukbare tekens om te kennen**

* **Zero width joiner (ZWJ)** , codepunt 200D (hexadecimaal), is, zoals de naam al aangeeft, ontworpen om het “verbindingsgedrag” van invoertekens te activeren—but alleen als die invoertekens *bezitten* een gedefinieerd verbindingsgedrag.
* **Zero width non-joiner (ZWNJ)** , codepunt 200C (hexadecimaal), is ontworpen om *voorkomen* het “verbindingsgedrag” te onderdrukken dat invoertekens anders zouden kunnen vertonen. Je kunt de ZWNJ bijvoorbeeld gebruiken om het verbindingsgedrag van opeenvolgende Arabische tekens te voorkomen die normaal gesproken in hun verbindingsvormen zouden worden verwerkt (gevormd).

Unicode heeft een lijst gepubliceerd van [Aanbevolen Emoji ZWJ-sequenties](https://unicode.org/emoji/charts/emoji-zwj-sequences.html) die een U+200D ZERO WIDTH JOINER (ZWJ) gebruiken om emoji-tekenreeksen samen te voegen tot één samengestelde emoji-glyph—als die beschikbaar is binnen de gebruikte font(s).

**Voorbeeld van gebruik van zero width non-joiner**

Het volgende minimale codefragment gebruikt het Scheherazade OpenType-font, opgenomen in TeX Live, om een LaTeX-font te definiëren met de naam `\arabicfont` dat we kunnen gebruiken om wat Arabisch te zetten. De regel

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

gebruikt een zero width non-joiner-teken, via `\Uchar"200C`om het normale verbindingsgedrag van de twee Arabische letters ل (lam) en ا (alef) te voorkomen. Let op het gebruik van `\textdir TRT` om de tekstrichting van rechts naar links in te stellen:

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

[Open dit LuaLaTeX-voorbeeld in 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)

Dit voorbeeld levert de volgende uitvoer op:

![NonJoiner.png](/files/bf39ac4fda6780e9d48c89f68549eb50d9381d93)

## Het concept “tekstvormgeving”

Laten we beginnen met een visueel voorbeeld met een Urdu-vertaling van het woord “educational”. Tekst van de Urdu-vertaling kan op een toetsenbord of touchscreenapparaat worden getypt en zou worden gemaakt als een eenvoudige lineaire reeks Unicode-Arabische tekens. Wanneer die tekst echter wordt gezet, of wordt weergegeven op het scherm van een apparaat in de [Nastaliq-stijl](https://en.wikipedia.org/wiki/Nastaliq) , ontstaat een complexe tweedimensionale rangschikking van glyphs.

Aan de hand van ons Urdu-voorbeeld vergelijkt de volgende afbeelding de lineaire invoer van Unicode-Arabisch *tekens* met de uitvoer gezet in Nastaliq-stijl, bestaande uit een tweedimensionale rangschikking van *glyphs* aanwezig in het (gratis) font [Awami Nastaliq](https://software.sil.org/awami/download/):

![](/files/f7ae79f65c82d1a49dafc216a7d077e8033003eb)

Het proces van het “vertalen” van invoertekens naar een set correct gepositioneerde uitvoerglyphs heet *tekstvormgeving*vormgeving, en is een vitaal onderdeel van tekstverwerking vóór weergave of zetwerk. Ons voorbeeld gebruikte tekst in de Urdu-taal (Arabisch schrift) omdat het resultaat van vormgeving duidelijk zichtbaar is, in tegenstelling tot talen die het Latijnse schrift gebruiken, zoals Engels, waar vormgeving veel minder uitgesproken is—zoals de vorming van eenvoudige ligaturen.

Tekstvormgeving is essentieel bij het gebruik van schriften (schrijfsystemen) zoals [Arabisch](https://en.wikipedia.org/wiki/Arabic), [Hebreeuws](https://en.wikipedia.org/wiki/Hebrew_language), [Devanagari](https://en.wikipedia.org/wiki/Devanagari) of [Malayalam](https://en.wikipedia.org/wiki/Malayalam)slechts vier voorbeelden van zogenaamde *complexe scripts* . Om een correcte presentatie van tekst in die scripts, en de talen die ze gebruiken, te garanderen, moet het vormgevingsproces zorgvuldig rekening houden met eventuele vormgevingsregels en nuances die aanwezig zijn in de specifieke combinatie van script en taal. Sommige talen vereisen bijvoorbeeld dat meerdere invoertekens een bepaald uitvoerglyph vormen, of er kunnen complexe vereisten zijn voor het zorgvuldig positioneren van diakritische tekens, en herordening tussen glyphs om ervoor te zorgen dat afzonderlijke glyphs correct gepositioneerd zijn (ten opzichte van elkaar).

In het algemeen vereist het vormgeven van een stuk tekst verschillende informatiebronnen:

* Het schrijfsysteem of *schrift* waarin de tekst is geschreven.
* De specifieke *taal* die wordt gebruikt. Voor meerdere talen kunnen afzonderlijke schriftsoorten worden gebruikt, waarbij elke combinatie van schrift en taal haar eigen vormgevingsfinesses/-nuances heeft.
* De schrijfrichting *richting* van de tekst—zoals van rechts naar links of van links naar rechts.
* A *lettertype* die de glyphs levert die nodig zijn om de gevormde tekst weer te geven en, optioneel, extra “vormgevingsregels” bevat die het tekstvormingsproces sturen.

De vereisten van tekstvormgeving, met name voor complexe schriften en hun bijbehorende talen, kunnen uiterst gedetailleerd en genuanceerd zijn, wat de behoefte aangeeft aan gespecialiseerde software die mogelijk zeer complexe “regels” voor tekstvormgeving kan toepassen. Het zal dan ook niet verbazen dat zulke software bestaat en wordt aangeduid als een *tekstvormingsengine*; de engine die we zullen bespreken heet [Harfbuzz](https://en.wikipedia.org/wiki/HarfBuzz), waarvan de documentatie het lezen waard is—bijvoorbeeld [Waarom heb ik een vormingsengine nodig?](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html).

**Verder lezen over tekstvormgeving**

Deze korte inleidingen worden sterk aanbevolen:

* [Wat is tekstvormgeving?](https://harfbuzz.github.io/what-is-harfbuzz.html#what-is-text-shaping)
* [Waarom heb ik een vormingsengine nodig?](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html)

**Technische noot: meerdere vormgevingstechnologieën (modellen)**

De HarfBuzz-tekstvormingsengine ondersteunt verschillende "vormingstechnologieën" die verschillen in hoe zij het vormingsproces implementeren—elke implementatie wordt aangeduid als een *shaper*, ook binnen de `luaotfload` documentatie. De focus van dit artikel ligt op OpenType-vormgeving, maar een alternatief, gratis te gebruiken technologie is [Graphite](https://scripts.sil.org/cms/scripts/page.php?site_id=projects\&item_id=graphite_aboutOT), ontwikkeld door [SIL International](https://www.sil.org/). Een ander vormingsmodel dat door HarfBuzz wordt ondersteund is [Apple Advanced Typography (AAT)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html)—fonts die AAT ondersteunen worden over het algemeen gebruikt op technologieplatforms van Apple.

**Voorbeeld met de Graphite-shaper**

Het volgende voorbeeld zet een deel Urdu-tekst op met een font genaamd [Awami Nastaliq](https://software.sil.org/awami/download/), dat Graphite-vormgeving ondersteunt en beschikbaar is op Overleaf. Awami Nastaliq is gemaakt door [SIL International](https://www.sil.org/), de organisatie die verantwoordelijk is voor de ontwikkeling van Graphite-technologie.

Het volgende voorbeeld demonstreert de geavanceerde vormgevingsmogelijkheden van op Graphite gebaseerde fonts—let op hoe de `luaotfload` fontdeclaratie Graphite-vormgeving selecteert met behulp van `shaper=graphite2`.

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

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

\vskip 75bp

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

[Open dit voorbeeld in 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)

Dit voorbeeld levert de volgende uitvoer op:

![](/files/c5b00145513fcd87b684fa98eb8206e492904252)

#### Emoji en tekstvormgeving

Tekstvormgeving is geïntroduceerd met voorbeelden uit een taal met een complex schrift, Urdu. Het kan echter verrassend zijn te horen dat het correct weergeven van emoji-glyphs tekstvormgeving vereist die wordt toegepast op Unicode-tekst met reeksen emoji-tekens—[zoals opgemerkt door de hoofdontwikkelaar van HarfBuzz](https://github.com/harfbuzz/harfbuzz/issues/2428#issuecomment-639108677):

> ...emoji vormgeven met HarfBuzz valt volledig binnen het toepassingsgebied en is feitelijk noodzakelijk om familie-emoji, huidkleur, enz. te krijgen.

We zullen hier voorbeelden van bekijken.

### Verdeling van verantwoordelijkheden: tekstvormingsengine + OpenType-fonts

In de praktijk is tekstvormgeving een “gezamenlijke operatie”, of taakverdeling, tussen de logica en regels die in de tekstvormingsengine zijn ingebouwd en extra vormgevingsregels en gegevens die in de gebruikte font(s) zijn ingebouwd—voortaan behandelen we OpenType-gebaseerde vormgeving *alleen*.

Om vormgeving uit te voeren krijgt de tekstvormingsengine doorgaans wat Unicode-tekst, een opgegeven schrift en taal, mogelijk een schrijfrichting en, het belangrijkst, een OpenType-font om te gebruiken tijdens het vormgevingsproces—het font levert de output: een set glyphs en positioneringsgegevens. Indien gewenst kan de vormingsengine extra regels toepassen ([OpenType-functies](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features)) die zijn opgenomen in het gebruikte OpenType-font—welke regels worden toegepast, is meestal door de gebruiker te kiezen uit de lijst met functies die het font ondersteunt.

Het resultaat van het vormgevingsproces is een *lijst met glyphs* die in het OpenType-font aanwezig zijn, samen met *inter-glyph* positioneringsgegevens. Die positioneringsgegevens hebben betrekking op *de relatieve plaatsing van de gevormde glyphs*; ze verwijzen niet naar absolute positionering binnen de opgemaakte pagina of andere media/inhoud zoals een webpagina, Tweet, enz. De renderingssoftware (zetprogramma, webbrowser, enz.) gebruikt de positioneringsinformatie tussen glyphs om ervoor te zorgen dat glyphs na assemblage en opname in de uiteindelijke uitvoer correct ten opzichte van elkaar worden gepositioneerd.

#### Wat is een lijst met glyphs?

Intern krijgt elke glyph binnen een OpenType-font een numerieke identificatie toegewezen, een gehele waarde die de glyph-index wordt genoemd—ook wel de glyph-identificatie of GID. Nadat de tekstvormingsengine zijn taak heeft voltooid, zal hij zijn resultaten teruggeven als een *lijst met glyph-identificaties* plus *positioneringsgegevens* voor die glyphs.

Afzonderlijke glyphs binnen OpenType-fonts krijgen indexen (identificaties) toegewezen door de maker van het font, waardoor het een zeer fontspecificieke en arbitraire waarde is—deze kan ook verschillen tussen versies van een bepaald font. Je mag nooit aannemen dat dezelfde GID-waarde van toepassing zal zijn op “vergelijkbare” glyphs in verschillende fonts; dat zal vrijwel zeker niet zo zijn. Als je een lijst met glyph-identificaties hebt die door een vormingsengine is geleverd, kun je die alleen gebruiken om glyphs te benaderen in het font waaruit ze zijn verkregen.

#### Wat zijn OpenType-fonts?

Het web is *overladen* met uitleg en details over OpenType-fonts, dus we beperken ons tot een korte beschrijving. De [OpenType-specificatie](https://docs.microsoft.com/en-us/typography/opentype/spec/) is een complex document bedoeld voor ontwikkelaars, maar in wezen definieert het een bestandsformaat, of container, voor fontgegevens. Een OpenType-font bevat gegevens die de glyphvormen beschrijven, samen met informatie over de ondersteunde schriftsoort(en) en taal/talen, metadata over het font en diverse “tabellen” die [typografische functies](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features) die door het font worden ondersteund, definiëren.

Een tekstvormingsengine kan doorgaans worden opgedragen om tijdens het vormgevingsproces selectief functies van een font toe te passen (te gebruiken), waarbij specifieke typografische effecten (“regels”) worden toegepast die de juiste set glyphs selecteren die in het font aanwezig zijn. Het gekozen font moet alle functies die de tekstvormingsengine moet toepassen ondersteunen en de bijbehorende glyphs leveren.

#### Geëcodeerde en niet-geëcodeerde “glyphs”

OpenType-fonts bevatten een gegevenstabel genaamd [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) (Character to Glyph Index Mapping) die de set Unicode-tekens, ondersteund door het font, toewijst aan de corresponderende glyph-index in dat font. De volgende video geeft een korte blik in de cmap-tabel in een font genaamd `lmmono10-regiular.otf` (opgenomen in TeX Live).

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

Fonts bevatten echter doorgaans veel glyphs die geen specifiek Unicode-teken vertegenwoordigen en niet als onderdeel van die cmap-tabel zijn opgenomen. Daardoor kan de set glyphs binnen een OpenType-font in twee hoofdsets worden verdeeld:

* gecodeerde glyphs die Unicode-tekens representeren;
* niet-gecodeerde glyphs die geen Unicode-tekens representeren.

Geëcodeerde glyphs kunnen worden benaderd door het juiste Unicode-teken in de tekst op te nemen—maar hoe zit het met niet-gecodeerde glyphs, hoe worden die gebruikt/benaderd? Die glyphs worden doorgaans gebruikt om de uitvoer van tekstvormingsbewerkingen te leveren, inclusief het toepassen van fontfuncties om specifieke visuele/typografische effecten te produceren.

### OpenType-kleurfonts

Van emoji-tekens wordt verwacht dat ze in volledige kleur worden weergegeven—zwarte-en-witte emoji bieden niet helemaal de “volledige emoji-ervaring”. Op het moment van de eerste codering van emoji door Unicode had de [OpenType-fontspecificatie](https://docs.microsoft.com/en-us/typography/opentype/spec/) geen geschikte voorziening voor het insluiten van *kleurrijke*-glyphgegevens in OpenType-fonts. Deze “kloof” in OpenType bracht toonaangevende technologie-/platformleveranciers ertoe oplossingen te zoeken, en de daaropvolgende “race” resulteerde in [verschillende voorstellen om OpenType uit te breiden](https://www.fontlab.com/news/color-font-format-proposals/) om OpenType-kleurfonts te ondersteunen—niet alleen voor het weergeven van kleurrijke emoji-tekens (glyphs), maar voor het in kleur renderen van elke glyph.

#### Vier varianten van OpenType-kleurfont

[Adobe, Microsoft, Google en Apple dienden elk voorstellen in](https://www.fontlab.com/news/color-font-format-proposals/) om OpenType uit te breiden met ondersteuning voor volledige-kleur OpenType-fonts en uiteindelijk werden vier voorstellen aangenomen en opgenomen in de formele OpenType-specificatie. Voor het gemak kunnen we die vier varianten grofweg groeperen in vectorgebaseerd en rastergebaseerd—maar, zoals in deze [GitHub-repository](https://github.com/simoncozens/test-fonts), is de OpenType-specificatie voldoende flexibel om OpenType-kleurfontbestanden te ondersteunen die die vier basistechnologieën combineren.

* **Vectorgebaseerde OpenType-fonts:**
* **Microsoft**: glyphvormen worden beschreven met behulp van een vorm van gelaagde kleurvectoren ([COLR](https://docs.microsoft.com/en-us/typography/opentype/spec/colr) en [CPAL](https://docs.microsoft.com/en-us/typography/opentype/spec/cpal) tabellen).
* [**Adobe en Mozilla**](https://www.w3.org/2013/10/SVG_in_OpenType/) ([SVG-tabel](https://docs.microsoft.com/en-us/typography/opentype/spec/svg)): glyphvormen worden getekend met behulp van SVG, dat glyphs ondersteunt die uit vectoren zijn opgebouwd *en rasterafbeeldingen*. Zie ook [Adobe’s gebruikershandleiding over SVG-fonts](https://helpx.adobe.com/fonts/user-guide.html/fonts/using/ot-svg-color-fonts.ug.html).
* **Rastergebaseerde OpenType-fonts:**
* **Google**: glyphs worden weergegeven door kleur-PNG-afbeeldingen die in het font zijn ingebed ([CBDT](https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt) en [CBLC](https://docs.microsoft.com/en-us/typography/opentype/spec/cblc) tabellen).
* **Apple**: glyphs worden ook weergegeven door kleurafbeeldingen die in het font zijn ingebed. Naast PNG ondersteunt Apples mechanisme ([sbix-tabel](https://docs.microsoft.com/en-us/typography/opentype/spec/colr)) ook JPEG en TIFF.

Daarmee moeten besturingssystemen en applicatiesoftware die OpenType-kleurfonts ondersteunen tegenwoordig omgaan met een landschap van gemengde technologieën. Verder moet je ervan bewust zijn dat afzonderlijke OpenType-kleurfonts—en *versies* van hetzelfde font—zullen:

* een andere dekking hebben van de volledige set [Unicode-emoji-tekens](https://unicode.org/emoji/charts/emoji-list.html)—d.w\.z. hoeveel emoji-tekens het font aan glyphs levert;
* verschillende glyphontwerpen gebruiken om individuele emoji-tekens weer te geven;
* verschillen in de functies die ze bieden ter ondersteuning van geavanceerdere toepassingen van de Unicode-standaarden, zoals [emoji-modifiers](https://unicode.org/reports/tr51/#Emoji_Modifiers_Table), en andere mogelijkheden voor emoji-tekstverwerking die worden beschreven in [Unicode Technical Standard #51: Unicode Emoji](https://unicode.org/reports/tr51/).

#### De ophef rond HarfBuzz

We hebben al gezinspeeld op de behoefte aan een *tekstvormingsengine*: software die wat invoer-Unicode-tekst neemt, geschreven met een specifieke combinatie van schrift en taal, en die tekst met een aangewezen font omzet in een reeks glyphs, samen met positioneringsgegevens, die kunnen worden gebruikt om de oorspronkelijke invoertekst op te maken.

[HarfBuzz](https://harfbuzz.github.io/) is zo'n tekstvormingsengine: het is [een open-source codebibliotheek](https://github.com/harfbuzz/harfbuzz) en het resultaat van meer dan een decennium onderzoek en ontwikkeling—en nog steeds actief in ontwikkeling en ingezet als onderdeel van veel softwareproducten. HarfBuzz zelf doet geen “zetwerk”, maar biedt “tekstvormingsdiensten” aan software die ervoor kiest het te integreren, waaronder XeTeX, LuaHBTeX, [Adobe PhotoShop en Adobe InDesign](https://en.wikipedia.org/wiki/HarfBuzz).

Door HarfBuzz op te nemen kunnen TeX-engines profiteren van de geavanceerde tekstvormingsmogelijkheden om zeer verfijnde meertalige opmaak te bieden, vooral voor complexe schriften zoals Arabisch, Hebreeuws, Devanagari en vele andere. Merk ook op dat HarfBuzz wordt gebruikt om Unicode-emoji-teksttekens te verwerken en vorm te geven, wat we in meer detail zullen verkennen.

De volgende afbeelding vat de rol samen die HarfBuzz speelt wanneer het wordt geïntegreerd met software zoals XeTeX of LuaHBTeX tijdens het opmaken van tekst in een complex schrift, zoals Arabisch:

![Een overzicht van Arabische tekstvormgeving met HarfBuzz](/files/2dc5eec00af89a4724bcc17795551c0b4258a365)

**HarfBuzz verkennen**

Wie meer wil weten over HarfBuzz en de OpenType-vormgevingsdiensten die het aan XeTeX en LuaHBTeX levert, kan [een binaire distributie van HarfBuzz downloaden](https://github.com/harfbuzz/harfbuzz/releases) die de HarfBuzz-bibliotheek (voor programmeurs) en opdrachtregelhulpprogramma's bevat `hb-view` en `hb-shape`.

**Voorbeeld: hoe hb-view te gebruiken**

Maak een nieuw bestand aan in je favoriete teksteditor met UTF-8-ondersteuning en kopieer/plak de volgende zes emoji-tekens 👋👋🏻👋🏼👋🏽👋🏾👋🏿 in dat tekstbestand, en sla het vervolgens op in UTF-8-formaat als een bestand met bijvoorbeeld de naam `emoji.txt`.

Merk op dat je teksteditor misschien (fallback-)zwart-witte versies van de emoji weergeeft, omdat hij niet in staat is (geprogrammeerd is) kleurglyphs weer te geven. Zodra deze 6 emoji zijn opgeslagen, moet het bestand `emoji.txt` de UTF-8-gegevens bevatten voor de volgende reeks Unicode-emoji-tekens—we hebben emoji-modifiers gescheiden met komma’s enkel voor *het leesgemak*:

* `1F44B` om 👋 te produceren
* `1F44B`, `1F3FB` om 👋🏻 te produceren
* `1F44B`, `1F3FC` om 👋🏼 te produceren
* `1F44B`, `1F3FD` om 👋🏽 te produceren
* `1F44B`, `1F3FE` om 👋🏾 te produceren
* `1F44B`, `1F3FF` om 👋🏿 te produceren

Er zou in totaal **11** Unicode-tekens moeten zijn, die elk 4 bytes aan UTF-8-gegevens genereren, dus het resulterende `emoji.txt` bestand zou 44 bytes lang moeten zijn, exclusief eventuele regeleindemarkeringen aan het einde van de regel die de emoji bevat.

De `hb-view` hulpprogramma kan het bestand `emoji.txt`, samen met een geschikt OpenType-kleurfont naar keuze, zoals `NotoColorEmoji.ttf`, gebruiken om een SVG-bestand van de door HarfBuzz gevormde output te genereren. Het volgende opdrachtregelvoorbeeld, dat op **één regel moet worden getypt** in je terminal, genereert het SVG-bestand `emoji.svg`:

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

Bij succesvolle uitvoering kan het bestand `emoji.svg`, gegenereerd door `hb-view`, worden geopend door Inkscape en zou er ongeveer zo uit moeten zien:

![Hbvieemoji.png](/files/acac8bcba135d7f1c397a47ddbff599388dd1f5d)

`hb-view` kan worden gebruikt om HarfBuzz-vormgeving te verkennen voor elk geschikt Unicode-tekstbestand en OpenType-font—het is zeker niet beperkt tot gebruik met emoji! Typ

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

om het grote aantal opdrachtregelopties voor dit krachtige en handige hulpprogramma te zien. Veel vormgevingsplezier!

## Tekstvormgeving en TeX-engines

Hier bekijken we de tekstvormingsmogelijkheden van XeTeX en de LuaTeX-familie van TeX-engines.

### XeTeX

XeTeX werd ontwikkeld in het begin van de jaren 2000 en was baanbrekend met verschillende innovaties in TeX-gebaseerde opmaak, met name *ingebouwde* ondersteuning voor:

* het lezen van Unicode-tekst in UTF-8-formaat;
* het gebruik van OpenType-fonts;
* tekstvormgeving voor meertalige opmaak;
* OpenType-gebaseerde wiskunde-opmaak.

XeTeX’s vermogen om complexe schrifttalen gemakkelijk en handig op te maken is te danken aan de ingebouwde tekstvormingsmogelijkheden—oorspronkelijk gebaseerd op de inmiddels verouderde [ICU LayoutEngine](http://userguide.icu-project.org/layoutengine). Dankzij het werk van Khaled Hosny stapte XeTeX over op het gebruik van HarfBuzz voor tekstvormgeving, zoals opgemerkt in een aankondiging van [maart 2013](https://tug.org/pipermail/xetex/2013-March/024118.html). Voor iedereen die meertalige tekst wil opmaken, wordt XeTeX doorgaans genoemd als de TeX-engine bij uitstek—maar er is nu een andere optie, LuaHBTeX, die we zullen verkennen.

### LuaTeX en LuaHBTeX

De ontwikkeling van LuaTeX begon rond 2005, maar volgde een heel andere ontwerpmethode dan XeTeX, dat nieuwe functies *rechtstreeks in* de XeTeX-software integreerde. In tegenstelling tot XeTeX kozen de ontwikkelaars van LuaTeX ervoor om "...een minimale set hulpmiddelen en geen oplossingen te bieden." (zie [Reference Manual for LuaTeX](https://www.pragma-ade.com/general/manuals/luatex.pdf)). In plaats van een reeks extra functies aan te bieden *die zijn ingebouwd in* LuaTeX-gebaseerde engines, worden de interne mechanismen van LuaTeX-engines opengelegd zodat ontwikkelaars en gevorderde gebruikers de geïntegreerde Lua-scripttaal kunnen benutten om hun eigen oplossingen te bouwen.

Zo kan de LuaTeX-engine, anders dan XeTeX, niet *rechtstreeks* OpenType-fonts gebruiken; in plaats daarvan moeten OpenType-fonts worden geladen en “voor gebruik voorbereid” via fontlaadfuncties die in Lua-code zijn geschreven. Die fontlaadfuncties worden aangeduid als *callback* functies: Lua-code die LuaTeX zal aanroepen (“uitvoeren”) wanneer een verzoek wordt gedaan om een font te laden.

Daarnaast biedt de LuaTeX-engine geen enkele *ingebouwde* tekstvormingsmogelijkheden—ook die moeten worden geleverd door externe code waarop de LuaTeX-engine een beroep kan doen om tekstvormingsdiensten te leveren. Ook dit contrasteert met de XeTeX-engine, die tekstvormingsmogelijkheden in de kernsoftware had opgenomen.

#### luaotfload: essentieel voor het gebruik van OpenType-fonts in LuaTeX/LuaHBTeX

LuaTeX’s callbackmechanisme voor fontladen biedt veel flexibiliteit, zij het ten koste van extra programmeren. Gelukkig voor gebruikers van LuaLaTeX heeft de TeX-community een pakket ontwikkeld genaamd `luaotfload`, dat deel uitmaakt van de [jaarlijkse release van TeX Live](https://www.tug.org/texlive/) en uiteraard beschikbaar is voor Overleaf-gebruikers.

`luaotfload` is [beschikbaar is op CTAN](https://ctan.org/pkg/luaotfload?lang=en) en heeft een [ontwikkelrepository op GitHub](https://github.com/latex3/luaotfload) waar je de laatste ontwikkelingen kunt volgen en [nieuwe releases](https://github.com/latex3/luaotfload/releases).

`luaotfload` kunnen rechtstreeks in de preambule van een LaTeX-document worden geladen via

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

Merk op dat `luaotfload` is de naam van een LaTeX *pakket*, wat betekent dat het de bestandsnaam heeft `luaotfload.sty`. Als je `luaotfload` met plain TeX wilde gebruiken, kun je dat doen door de regel

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

aan je plain-TeX-document toe te voegen.

Normaal gesproken hoeven gebruikers van LuaLaTeX—d.w\.z. degenen die LaTeX opmaken met LuaTeX/LuaHBTeX—niet rechtstreeks met `luaotfload` te werken, omdat de [`fontspec` pakket](https://ctan.org/pkg/fontspec) de `luaotfload` package voor je zal laden en via gebruikersgerichte commando’s die door de `fontspec` pakket niet te gebruiken.

### LuaHBTeX: nieuwe opties voor tekstvormgeving

`luaotfload` is een volwassen en krachtige Lua-bibliotheek die LuaTeX’s omgang met OpenType-fonts verzorgt—samen met het leveren van tekstvormingsdiensten voor een reeks talen en schriften. Oorspronkelijk werden de tekstvormingsfuncties van `luaotfload` geïmplementeerd in zuivere Lua-code, maar de release van TeX Live 2020 bracht een andere gangbare optie voor tekstvormgeving: een nieuwe op LuaTeX gebaseerde engine genaamd LuaHBTeX.

De “HB” in LuaHBTeX staat voor HarfBuzz—in wezen is LuaHBTeX de oorspronkelijke LuaTeX-engine *plus* met een geïntegreerde HarfBuzz-tekstvormingsengine. In lijn met de ontwerpmethode van LuaTeX zorgt de beschikbaarheid van HarfBuzz niet *automatisch* ervoor dat tekst door LuaHBTeX wordt gevormd: HarfBuzz is een ander hulpmiddel dat kan worden gebruikt om tekstvormingsoplossingen te bouwen.

LuaHBTeX’s integratie van HarfBuzz is [programmeerbaar via Lua-code](#introduction-to-the-luahbtex-harfbuzz-api), wat de ontwikkelaars van `luaotfload`heeft in staat gesteld HarfBuzz-gebaseerde tekstvormingsoplossingen toe te voegen. Daarom is [beginnend met versie 3.1, uitgebracht op 5 november 2019](https://github.com/latex3/luaotfload/releases/tag/v3.1), `luaotfload` verbeterd om gebruik te maken van HarfBuzz—waardoor HarfBuzz’s tekstvormingsmogelijkheden gemakkelijk toegankelijk worden voor de gemiddelde gebruiker.

Lezers die geïnteresseerd zijn in de technische details van HarfBuzz-integratie met LuaTeX kunnen dit [artikel van Khaled Hosny](https://www.tug.org/TUGboat/tb40-1/tb124hosny-harfbuzz.pdf).

### luaotfload: twee opties voor tekstvormgeving (wanneer HarfBuzz gebruiken?)

Gebruikers van LuaLaTeX hebben nu twee opties voor tekstvormgeving:

* `luaotfload`’s oorspronkelijke (node-gebaseerde) implementatie van tekstvormgeving, volledig geschreven in Lua;
* `luaotfload`’s HarfBuzz-gebaseerde vormgeving—benaderd via Lua-code die de tekstvormingsfuncties van HarfBuzz aanroept.

`luaotfload` biedt toegang tot deze twee vormingssystemen via de “`mode`”-parameter—hoewel de meeste gebruikers de equivalente `fontspec` “`Renderer`” optie zullen gebruiken in plaats van rechtstreeks de functies op een lager niveau van `luaotfload`.

Elk van `luaotfload`’s tekstvormingsoplossingen heeft zijn sterke punten en (huidige) zwakke punten, maar welke moet je gebruiken, en wanneer? Hier zijn enkele punten om te overwegen:

* `luaotfload`’s native node-gebaseerde verwerking kan veel geheugen vergen, vooral bij grote CJK OpenType-fonts. HarfBuzz gebruiken voor CJK-tekstvorming kan snelheidsverbeteringen en minder geheugengebruik opleveren.
* Gebruik HarfBuzz voor complexe schriften omdat het "...de weergave van Indiase en Arabische schriften sterk verbetert en voor dergelijke schriften sterk wordt aanbevolen." (zie `luaotfload` handleiding).
* HarfBuzz’s integratie in `luaotfload` is nog relatief nieuw en wordt verder ontwikkeld. Ten tijde van schrijven (juli 2021) is het raadzaam luaotfload’s ingebouwde vormgeving te gebruiken (instellen `mode=node`) voor de fonts van je hoofddocument, vooral als je document het Latijnse schrift gebruikt. Zie deze [GitHub-issue](https://github.com/latex3/luaotfload/issues/175#issue-801120377), waarin de problemen en discussies worden samengevat. Als je wilt experimenteren, kun je `luaotfload` gebruiken om een fontbestand te laden en twee LaTeX-fonts te maken: één dat HarfBuzz-gebaseerde vormgeving gebruikt en de andere die Lua-gebaseerde vormgeving gebruikt. Overleaf maakte een [voorbeeldproject](#sample-project-arabic-shaping), dat dit demonstreert.
* Gebruik HarfBuzz niet voor het verwerken van wiskundige fonts. Zoals besproken door ontwikkelaars op tex.stackexchange, is HarfBuzz [niet ontworpen om fonts voor wiskundige opmaak te verwerken](https://tex.stackexchange.com/questions/544881/does-luahbtex-with-harfbuzz-renderer-completely-supports-math-formating) dus gebruik het niet voor dat doel.

**Voorbeeldproject: Arabische vormgeving**

Hier is een Overleaf-project dat verschillende hoogwaardige Arabische lettertypen gebruikt om te vergelijken `luaotfload`’s node-gebaseerde tekstvormingsdiensten (`mode=node`) met die van HarfBuzz (`mode=harf`):

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

Dit project bevat uitvoer die in de volgende afbeelding wordt getoond:

![Arabisch opmaken](/files/1b5c2a2a82e231131f1fe6b87f876964a1b2d96a)

### De “Renderer” kiezen in fontspec

Zoals opgemerkt in de [documentatie](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), `fontspec` “...stelt gebruikers van zowel XeTeX als LuaTeX in staat OpenType-fonts te laden in een LaTeX-document”. Als je de LuaTeX- of LuaHBTeX-engines gebruikt, `fontspec` de `luaotfload` bibliotheek voor je en bieden daarnaast een reeks handige gebruikersgerichte commando’s die de noodzaak verminderen om met `luaotfload`’s functionaliteit op een laag niveau te werken.

Hoe kies je dan tussen HarfBuzz-vormgeving of de ingebouwde vormgeving die wordt geleverd door `luaotfload`? Het antwoord staat in de uitstekende [`fontspec` documentatie](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), specifiek Deel VI: fontfuncties alleen voor LuaTeX. `fontspec` biedt een instelling genaamd `Renderer` die kan worden ingesteld wanneer het font wordt gedefinieerd via `fontspec`. `Renderer` stuurt de verwerking van het font op laag niveau aan. De twee interessante opties zijn

* `Renderer = Node`: de standaard “mode” voor het opmaken van OpenType-fonts—dit gebruikt `luaotfload`’s tekstvormingsfuncties, volledig geïmplementeerd in Lua.
* `Renderer = Harfbuzz`: deze “mode” definieert/laadt het font voor gebruik met de HarfBuzz-tekstvormingsengine. `luaotfload` gebruikt LuaHBTeX’s API om functies in HarfBuzz aan te roepen.

Voor meer informatie zie de [`fontspec` documentatie](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf).

## TeX-engines, HarfBuzz en kleur-emoji

Hoewel XeTeX en LuaHBTeX beide HarfBuzz integreren, bieden ze verschillende niveaus van ondersteuning voor enkele van HarfBuzz’s meer geavanceerde functies—met name het laden en gebruiken van OpenType-kleurfonts.

### XeTeX en OpenType-kleurfonts

Zoals opgemerkt zijn er twee categorieën OpenType-kleurfonts op basis van het gegevensformaat dat wordt gebruikt om de glyphs van het font op te slaan: vectorgebaseerd en rastergebaseerd.

#### XeTeX en rastergebaseerde OpenType-kleurfonts

XeTeX kan rastergebaseerde OpenType-kleurfonts niet laden—zoals Google’s [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/) meegeleverd bij TeX Live 2020. Als je bijvoorbeeld Noto Color Emoji (NotoColorEmoji.ttf) probeert te laden, zal XeLaTeX mislukken met een mogelijk misleidende fout waarin wordt beweerd dat Noto Color Emoji “niet kan worden gevonden”. De volgende LaTeX-code, gezet met XeLaTeX, *werkt niet*:

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

[Open deze XeLaTeX-code in Overleaf (het ***doet niet*** werkt).](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)

Het mislukt met de foutmelding:

```
! Package fontspec-fout: Het lettertype "NotoColorEmoji" kan niet worden gevonden.
```

Op vergelijkbare wijze mislukt ook een eenvoudig Plain TeX-voorbeeld verwerkt door XeTeX

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

[Open dit Plain TeX-(XeTeX)-voorbeeld in Overleaf (het ***doet niet*** werkt).](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)

Het Plain TeX-voorbeeld meldt een soortgelijke, maar andere, foutmelding:

```
! Lettertype \emojifont=[NotoColorEmoji.ttf] op 12.0pt kan niet worden geladen: Metric (TFM)-bestand
of geïnstalleerd lettertype niet gevonden.
l.1 \font\emojifont="[NotoColorEmoji.ttf]" at 12pt

Ik kon de groottegegevens voor dit lettertype niet lezen,
dus ik negeer de lettertypespecificatie.
[Wizards kunnen TFM-bestanden repareren met TFtoPL/PLtoTF.]
Je kunt proberen een andere fontspecificatie in te voegen;
bijv. typ `I\font<zelfde font-id>=<vervangende fontnaam>'.
```

**Eenvoudig Plain LuaHBTeX-voorbeeld**

Ter vergelijking, hier is een minimaal Plain TeX-voorbeeld gecompileerd met LuaHBTeX

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

[Open dit Plain TeX-(LuaHBTeX)-voorbeeld in Overleaf (het compileert succesvol).](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)

#### De werkelijke oorzaak van XeTeX’ mislukking

De foutmeldingen van XeTeX verhullen gedeeltelijk de werkelijke oorzaak van het probleem: OpenType-kleurfonts, met name rastergebaseerde varianten, worden *niet* ondersteund door XeTeX. In werkelijkheid kan XeTeX (Kpathsea) *vinden* het Noto Color Emoji-font, maar XeTeX kan dat font niet volledig *laden* en kan de interne fontdatatabellen die nodig zijn om dat font voor zetwerk te gebruiken niet initialiseren. Intern voert XeTeX *begint* het proces van het laden van het font uit en test het op “schaalbaarheid” (met gebruik van FreeType’s “definitie” van “schaalbaarheid”), maar die test mislukt, en XeTeX geeft een standaard, mogelijk misleidende foutmelding van de TeX-engine.

**TeXnische noot**

De verwerking door XeTeX van NotoColorEmoji.ttf werd onderzocht door een debugversie van het XeTeX-uitvoerbare bestand te compileren. De Eclipse IDE werd gebruikt om een breakpoint in te stellen op de XeTeX-functie `creatFontFromFile(filename, index, pointsize)`, en vervolgens door de code te stappen om de verdere verwerking te observeren.

#### XeTeX en vectorgebaseerde OpenType-kleurfonts

XeTeX kan *laden* vectorgebaseerde OpenType-kleurfonts laden, maar zal geen kleur-emoji in de resulterende PDF produceren—als XeTeX er überhaupt een produceert. In tegenstelling tot LuaTeX, LuaHBTeX en pdfTeX geeft XeTeX geen *rechtstreeks* opgemaakte documenten uit in PDF-formaat. In plaats daarvan voert XeTeX een tussenliggend `.xdv` (e**x**xtended **dv**i) bestandsformaat uit dat naar PDF wordt geconverteerd door een hulpprogramma genaamd `xdvipdfmx`. Op het moment van schrijven, `xdvipdfmx` kan de juiste kleur-emoji-glyfgegevens niet in de PDF insluiten, dus hooguit zie je monochrome emoji—het “fallback”-resultaat—in de PDF, of misschien helemaal niets, afhankelijk van het gebruikte font.

Hier is een XeLaTeX-voorbeeld dat het OpenType-kleurfont gebruikt [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr), beschikbaar in TeX Live. TwemojiMozilla.ttf gebruikt Microsofts COLR/CPAL-vectorformaat voor het opslaan van kleur-glyphs en wordt meegeleverd met TeX Live 2020. In dit voorbeeld kan XeTeX het font laden, een `.xdv` en PDF-bestand genereren, maar de emoji-glyf is niet aanwezig in de opgemaakte PDF:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}
\newcommand{\smiley}{{\emojifont\char\"1F600}}
Hier is een smiley: \smiley
\end{document}
```

[Open deze XeLaTeX-code in Overleaf (het WERKT NIET).](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)

Daarentegen werkt de code hierboven met LuaLaTeX als je definieert `\emojifont` met behulp van de `fontspec` instelling `[Renderer=HarfBuzz]`:

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

[Open deze LuaLaTeX-code in Overleaf (het werkt).](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 en OpenType-kleurfonts

Dankzij zijn geïntegreerde HarfBuzz-opmaakengine en de `luaoftload` bibliotheek biedt LuaHBTeX ondersteuning voor alle vier varianten van OpenType-kleurfont. Gebruikers van LuaLaTeX kunnen volledig profiteren van Unicode-gebaseerde verwerking van tekst die emoji-tekens bevat of hun documenten eenvoudig verfraaien met zeer kleurrijke tekst met behulp van OpenType-kleurfonts.

Zoals eerder opgemerkt kunnen de vier varianten van OpenType-kleurfont worden ingedeeld in twee groepen:

* die glyphs in rasterafbeeldingsformaten bevatten, zoals PNG;
* andere die vectorgebaseerde formaten zoals SVG of Microsofts COLR/CPAL-mechanisme gebruiken.

Vectorgebaseerde glyphformaten hebben het voordeel van schaalbaarheid: ze produceren scherpe glyph-afbeeldingen op elke puntgrootte.

**Microsoft COLR/CPAL-kleurfonts gebruiken met LuaHBTeX**

Als je een vectorformaat wilt gebruiken voor je OpenType-kleur-emoji-fonts, bekijk dan het font [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr?lang=en), dat gebaseerd is op Microsofts COLR/CPAL-formaat. TwemojiMozilla.ttf is inbegrepen bij TeX Live, maar je kunt de nieuwste versie verkrijgen via zijn [GitHub-repository](https://github.com/mozilla/twemoji-colr/releases) en deze uploaden naar je Overleaf-project.

Hier is een kleine, `fontspec`-gebaseerde, voorbeeld met `Renderer=Harfbuzz`, dat een grote (vector)eend-emoji zet:

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

[Open dit LuaLaTeX-voorbeeld om een vector-eend te zetten.](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)

Hier is de (vector)eend die door het bovenstaande voorbeeld wordt geproduceerd:

![](/files/8eed2820beadedd7c1070889e7f56b64c052cdb8)

#### Het gebruik van op SVG gebaseerde OpenType-kleurfonts met LuaHBTeX

Op het moment van deze artikelupdate (juli 2023) is er weinig formele documentatie over het gebruik van OpenType-kleurfonts in SVG-stijl met LuaLaTeX. Sommige [opmerkingen in online discussies](https://github.com/latex3/luaotfload/issues/96) suggereren het gebruik van `fontspec`voorstelt: `RawFeature`, zoals getoond in de pseudocode hieronder. Vervang `*your SVG font file name here*` door de naam van een op SVG gebaseerd fontbestand dat toegankelijk is voor je LaTeX-code:

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

Als je `fontspec` weglaat en `luaotfload` rechtstreeks laadt, moet je mogelijk op de volgende manier een font declareren en specificeren—onze experimenten geven aan dat je de `mode=harf` optie moet weglaten om dit te laten werken:

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

**Enkele kanttekeningen**

Lezers die geïnteresseerd zijn in het gebruik van OpenType-kleurfonts in SVG-stijl moeten opmerken:

* OpenType-fonts in SVG-stijl die een groot aantal glyphs bevatten kunnen [rekenkundig kostbaar zijn voor LuaLaTeX](#processing-svg-glyph-data) om te verwerken, wat mogelijk leidt tot [Overleaf-time-outs](/latex/nl/kennisbank/038-fixing-and-preventing-compile-timeouts.md).
* De ondersteuning van LuaLaTeX voor deze fonts kan worden [beschouwd als experimenteel](https://github.com/latex3/luaotfload/issues/96#issuecomment-530317399): de resultaten kunnen variëren afhankelijk van de TeX Live-release die door je project wordt gebruikt; daarom is het raadzaam te experimenteren en voorzichtig te werk te gaan.

**SVG-glyphgegevens verwerken**

SVG stelt ontwerpers in staat complexe en kleurrijke ontwerpen te maken die de glyphs van een font weergeven—onderhevig aan enkele SVG-beperkingen [die gedocumenteerd zijn in de OpenType-specificatie](https://docs.microsoft.com/en-us/typography/opentype/spec/svg). TeX-engines, inclusief LuaHBTeX, kunnen SVG-bestanden of -gegevens—zoals de SVG-gegevens die worden gebruikt om glyphvormen binnen OpenType-kleurfonts in SVG-stijl te beschrijven—niet rechtstreeks importeren (gebruiken). De SVG-gegevens van een glyph moeten naar PDF-formaat worden geconverteerd omdat LuaHBTeX die kan gebruiken om de glyph te zetten en het uiteindelijke PDF-document te produceren. Die SVG-naar-PDF-conversie wordt afgehandeld door Lua-code binnen `luaoftload`: de SVG-gegevens van elke glyph worden uit het fontbestand geëxtraheerd, opgeslagen in een tijdelijk `.svg` bestand en geconverteerd naar PDF met Inkscape via de opdrachtregel. Het extraheren van de SVG-gegevens en het converteren ervan naar PDF brengt enige verwerkings-overhead met zich mee, wat kan leiden tot langdurige documentcompilatietijden—vooral bij documenten die grote SVG-fonts met duizenden emoji-glyphs gebruiken.

#### Rastergebaseerde OpenType-kleurfonts

**Google’s CBDT/CBLC OpenType-kleurfontformaat gebruiken met LuaHBTeX**

[Noto Color Emoji](https://fonts.google.com/noto/specimen/Noto+Color+Emoji) is een OpenType-kleurfont dat is inbegrepen bij TeX Live, waardoor het gemakkelijk te gebruiken is in een Overleaf-project. Omdat Noto Color Emoji PNG-afbeeldingen gebruikt om emoji-glyphs weer te geven, kunnen we het gebruiken om een grote (raster)eend-emoji te zetten—zoals gedemonstreerd door het volgende voorbeeld. Merk opnieuw op dat de `fontspec` fontdeclaratie (`\emojifont`) gebruikt `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}
```

[Open dit LuaLaTeX-voorbeeld om een rastereend te zetten.](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)

Hier is de rastereend die door het bovenstaande voorbeeld wordt geproduceerd:

![Een door LaTeX gezette rastereend-emoji](/files/e11ab1fa3c298785fa621dfdf500440da2326c61)

Als je probeert `NotoColorEmoji.ttf` maar weglaat `[Renderer=Harfbuzz]` uit de `fontspec` declaratie, zal LuaHBTeX falen en een foutmelding geven wanneer het probeert het PDF-bestand weg te schrijven:

```latex
! fout:  (bestand /usr/local/texlive/2020/texmf-dist/fonts/truetype/google/noto-em
oji/NotoColorEmoji.ttf) (ttf): loca-tabel niet gevonden
```

De reden voor deze fout in de [loca-tabel](https://docs.microsoft.com/en-us/typography/opentype/spec/loca) is [uitgelegd op GitHub](https://github.com/latex3/luaotfload/issues/98#issuecomment-531610153).

**Apple’s sbix OpenType-kleurfontformaat gebruiken met LuaHBTeX**

Offline tests tonen aan dat LuaHBTeX de `sbix` variant van OpenType-kleurfont ondersteunt, maar op het moment van schrijven van dit artikel hebben we geen geschikt gelicentieerd `sbix`-variant kleur-emoji-font kunnen vinden om het zetten van een eend te demonstreren. Laat [contact met ons op](https://www.overleaf.com/contact) het ons alstublieft weten als je er een kent, en dan werken we dit artikel kwakend snel bij om die te gebruiken.

## Inleiding tot de LuaHBTeX HarfBuzz-API

![Db.gif](/files/69bc0934084b18a6407c24a0af31dce3d6ede119) ![Db.gif](/files/69bc0934084b18a6407c24a0af31dce3d6ede119)

Tekstvormgeving, met name voor talen met complexe schriftsoorten, en zelfs emoji, is een inherent moeilijke taak, dus het is niet verrassend dat HarfBuzz een geavanceerde bibliotheek is waarmee moeilijk te werken kan zijn—tenzij je al vertrouwd bent met tekstvormingsbewerkingen. In dit laatste gedeelte bekijken we LuaHBTeX’ integratie van HarfBuzz en hoe je er toegang toe krijgt via Lua-code binnen `\directlua`.

Ons voorbeeld gebruikt vrij eenvoudige code om de LuaHBTeX HarfBuzz-API te demonstreren. Het is enigszins geforceerd, niet van productiekwaliteit en niet erg praktisch, omdat het enige doel is enkele kernideeën te introduceren. We hebben de Lua-code opgesplitst in twee `\directlua` stukken: het eerste laadt de `luaharfbuzz` bibliotheek en creëert enkele globale variabelen die we in ons tweede `\directlua` stuk gebruiken, waarin we een macro definiëren met de naam `\codestoemoji`.

Het voelt passend om Knuths gebruik van dubbele gevaarlijke-bochttekens te kopiëren (afbeelding met dank aan [deze site](http://www.truetex.com/db.htm)) omdat de inhoud enigszins laagdrempelig is en “onder de motorkap kijkt”—al hopen we dat het voor de meer avontuurlijke lezer interessant kan zijn. LuaHBTeX’ integratie van HarfBuzz is afgeleid van het [luaharfbuzz-project op GitHub](https://github.com/ufyTeX/luaharfbuzz/wiki#projects-using-luaharfbuzz) waar je een [inleiding tot het project](https://github.com/ufyTeX/luaharfbuzz/wiki) samen met een [lijst van de luaharfbuzz-API](http://ufytex.github.io/luaharfbuzz/).

### Eerste stappen: laad de luaharfbuzz-bibliotheek en vind een font

Om de HarfBuzz-API van LuaHBTeX te gebruiken moeten we eerst de bibliotheek (module) laden met de naam `luaharfbuzz`, ingebouwd in LuaHBTeX, en de geretourneerde tabel opslaan in een (globale) variabele die we `hblib`:

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

Vervolgens moeten we een geschikt emoji OpenType-kleurfont vinden: we gebruiken Noto Color Emoji—merk op dat we hier erg lui zijn en geen foutcontrole doen voor het geval we het niet vinden! Om het te vinden gebruiken we de `kpse` (Kpathsea)-bibliotheek, die ook deel uitmaakt van LuaTeX/LuaHBTeX:

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

Nu we toegang hebben tot de HarfBuzz-bibliotheek via onze variabele `hblib`, en het pad naar een geschikt font (`pathtofontfile`), kunnen we beginnen met het gebruik van `hblib`. Om te beginnen maken we een HarfBuzz-font en HarfBuzz-face voor gebruik in het tweede `\directlua` codeblok waarin we onze macro definiëren.

```latex
%Maak een HarfBuzz-face en HarfBuzz-font van Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)
```

#### HarfBuzz-font en HarfBuzz-face: wat zijn dat?

A [HarfBuzz-face-object](https://harfbuzz.github.io/fonts-and-faces.html) vertegenwoordigt een lettertypefamilie die is geladen uit een fontbestand, maar zonder dat specifieke parameters (zoals grootte) zijn ingesteld. Een [HarfBuzz-fontobject](https://harfbuzz.github.io/fonts-and-faces.html) vertegenwoordigt een *specifieke instantie* van een HarfBuzz-face; bijgevolg kunnen uit één HarfBuzz-face verschillende HarfBuzz-fontobjecten worden afgeleid: elk HarfBuzz-font kan zijn eigenschappen, zoals grootte, op verschillende waarden hebben ingesteld. Een HarfBuzz-face is een hoger abstractieniveau dan een HarfBuzz-font.

### Fontglyphs gebruiken om PNG-bestanden te maken

Het laatste deel van ons eerste `\directlua` codeblok is een functie met de naam `writePNGglyph(hbfontobject, glyphID)` die we gebruiken om te demonstreren dat sommige OpenType-kleurfonts, zoals Noto Color Emoji, PNG-afbeeldingen gebruiken om de emoji-glyphs die het bevat weer te geven.

Deze functie gebruikt de HarfBuzz-API van LuaHBTeX om PNG-gegevens uit glyphs te extraheren en die gegevens naar een `.png` bestand met de naam `Graphics<glyphID>.png`. De naam van dat `.png` bestand wordt teruggegeven voor gebruik door `\includegraphics` om PNG-glyfafbeeldingen in onze opgemaakte PDF in te sluiten.

Met de `writePNGglyph(hbfontobject, glyphID)` op zijn plaats, ziet ons eerste `\directlua` codeblok er als volgt uit:

```latex
\directlua{

% Laad de luaharfbuzz-bibliotheek vanuit LuaHBTeX
hblib=require("luaharfbuzz")

% Zoek het Noto Color Emoji-font op de server van Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Maak een HarfBuzz-face en HarfBuzz-font van Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% Deze functie accepteert een font en een glyph-ID:
% het extraheert de PNG-gegevens van de glyphs en schrijft
% die naar een .png-bestand

function writePNGglyph(hbfontobject, glyphID)

    % Verkrijg PNG-gegevens van de glyph
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % Maak een bestandsnaam voor ons .png-bestand
    local fname="Glyph"..glyphID..".png"

    % Schrijf het .png-bestand en geef de bestandsnaam terug
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % Geef de bestandsnaam terug voor \includegraphics om te gebruiken
    return fname
end
}
```

### Tweede \directlua-codeblok: maak de macro \codestoemoji

Het doel is een macro te definiëren `\codestoemoji` die we kunnen aanroepen met een stuk tekst dat emoji-tekencodes bevat die we HarfBuzz willen laten vormgeven. Concreet gebruiken we `\Uchar<tekencode>` om elk emoji-teken voor te stellen; bijvoorbeeld:

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

Er gebeurt veel binnen de definitie van `\codestoemoji` die we hieronder zullen uitleggen, maar de definitie ziet er als volgt uit:

```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()
    % De glyphs-tabel, hbglyphs, is 1-gebaseerd
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % Verklein de grootte van onze geïmporteerde PNG-afbeeldingen
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}
```

#### De definitie van de macro \codestoemoji begrijpen

De `\codestoemoji` macro is grotendeels Lua-code die is opgenomen binnen `\directlua`, dus als je meer wilt weten over *hoe* `\directlua` werkt, bekijk dan het Overleaf-artikel [Begrijpen `\directlua`](/latex/nl/diepgaande-artikelen/09-an-introduction-to-luatex-part-2-understanding-directlua.md). Het legt uit hoe LuaTeX en LuaHBTeX verwerken `\directlua` wanneer TeX/LaTeX-opdrachten in de Lua-code zijn opgenomen en, in het bijzonder, de noodzaak om `\noexpand` en `\unexpanded`.

**Omgaan met de macroparameter: "#1"**

De macro begint met deze drie regels:

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

die de volgende taken uitvoeren:

* `local str="#1"`: hiermee wordt een Lua-tekenreeks gemaakt van de invoer die door de macro wordt doorgegeven;
* `local hbbuffer = hblib.Buffer.new()`: hiermee wordt de HarfBuzz-API gebruikt om een buffer te maken om de tekst in op te slaan die we HarfBuzz willen laten vormgeven;
* `hbbuffer:add_utf8(str)`: hiermee wordt een UTF-8-opgemaakte tekenreeks, gemaakt op basis van de invoer van onze macro, aan de HarfBuzz-buffer toegevoegd.

De eerste regel code

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

lijkt vrij eenvoudig, maar de werking ervan omvat behoorlijk wat complexiteit, die het waard is om wat nader te onderzoeken.

Als we de derde regel code bekijken

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

zien we dat deze onze `str` variabele gebruikt om de HarfBuzz-buffer een Unicode-tekenreeks in UTF-8 te geven. Om dat te laten werken, moet de variabele `str` zelf ook Unicode-tekst in UTF-8 bevatten; dus rijst de vraag: *hoe* heeft LuaHBTeX het macro-argument `"#1"`, dat `\Uchar` opdrachten bevat, omgezet naar de Lua-tekenreeksvariabele `str` die UTF-8-tekst voor HarfBuzz bevat?

Als we kijken naar ons beoogde gebruik van de `\codestoemoji` macro:

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

de invoer, zoals `\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065...`, lijkt in de verste verte niet op een reeks emoji-tekens gecodeerd in UTF-8. Bovendien weet HarfBuzz niets van TeX-opdrachten. Op de een of andere manier wordt de ruwe TeX-invoer bestaande uit `\Uchar` opdrachten omgezet in Unicode-tekens gecodeerd in UTF-8 die HarfBuzz kan gebruiken, maar *hoe*?

Het antwoord ligt in het gedrag van de `\Uchar` opdracht: proberen aan te roepen `\codestoemoji` met behulp van `\char` in plaats van `\Uchar` zal mislukken, maar *waarom*?

**\Uchar: expansie in \directlua**

Wanneer de `\codestoemoji` macro wordt aangeroepen, moet de `\directlua` opdracht, opgeslagen in de definitie van de macro, Lua-code voorbereiden om naar de ingebouwde Lua-interpreter van LuaHBTeX te sturen. Een deel van dat codevoorbereidingsproces is het uitbreiden van alle TeX/LaTeX-opdrachten die aanwezig zijn in de oorspronkelijke Lua-code in de definitie van de macro, samen met het uitbreiden van eventuele macro-argumenten die door de gebruiker zijn opgegeven. Dat uitbreidingsproces levert een tokenlijst op die vervolgens weer naar tekst wordt omgezet, waardoor de Lua-code ontstaat die naar de Lua-interpreter wordt doorgegeven. Ter wille van het gemak nemen we een diagram over uit het Overleaf-artikel [Begrijpen `\directlua`](/latex/nl/diepgaande-artikelen/09-an-introduction-to-luatex-part-2-understanding-directlua.md):

![De werking van \directlua](/files/78e977e8af3210f4b126b4f6e92fb91f76aadd90)

De macro `\codestoemoji` is bedoeld om te worden aangeroepen met `\Uchar` opdrachten en, [zoals eerder in het artikel opgemerkt](#the-key-difference-expansion), `\Uchar` is een uitbreidbaar commando waarvan de expansie een teken-token genereert. Binnen de verwerkingsactiviteiten van `\directlua`, breidt LuaHBTeX elke `\Uchar<tekencode>` opdracht uit waar het *verwijdert* elk `\Uchar<tekencode>` uit de invoer verwijderd en *vervangt* vervangt door de overeenkomstige expansiewaarde: een teken-token dat de `<tekencode>`.

In de laatste verwerkingsfase wordt de initiële tokenlijst gegenereerd door `\directlua` omgezet *terug naar tekst* om de Lua-code te worden die bestemd is voor de Lua-interpreter (zie diagram hierboven). Alle teken-tokens die worden geproduceerd door de expansie van `\Uchar` worden ook *terug naar tekst omgezet*: die conversie van karaktertokens naar tekst genereert de UTF-8-weergaven van de oorspronkelijke `<tekencode>` waarden.

In ons voorbeeld is, tegen de tijd dat de Lua-code is gegenereerd en klaar is voor de Lua-interpreter, de macro-invoer voor "#1" omgezet in een reeks UTF-8-tekst: de `str` variabele is nu een UTF-8-tekststring die veilig aan de HarfBuzz-buffer kan worden toegevoegd.

**Waarom werkt \char niet?**

Het korte antwoord is dat `\char` is *niet* een uitbreidbaar commando. In tegenstelling tot `\Uchar` commando's, `\char` commando's *worden niet verwijderd* uit de invoer tijdens `\directlua`de eerste verwerking van om een tokenlijst te genereren, ze “passeren” en worden opgenomen in de tokenlijst die wordt opgebouwd door `\directlua`. Als bijvoorbeeld het argument voor `\codestoemoji` bevatte `\char"1F3F4` LuaHBTeX zou dat omzetten in een reeks tokens en die opslaan als onderdeel van de totale tokenlijst die wordt gegenereerd.

In de volgende verwerkingsfase, waarin de tokens weer naar tekst worden omgezet, zou de resulterende Lua-code de *letterlijke string* `\char"1F3F4` bevatten binnen de tekst die wordt gebruikt om onze variabele te definiëren `str`. Wanneer de inhoud van `str` aan de HarfBuzz-buffer wordt toegevoegd, zal deze geen UTF-8-gecodeerde reeks bevatten die het emoji-teken "1F3F4 vertegenwoordigt; hij zou de letterlijke string bevatten `\char"1F3F4`, die HarfBuzz zal proberen vorm te geven en die, voor onze doeleinden, geen emoji-glyph zou opleveren. Trouwens, de string `\char"1F3F4` zou ook Lua-syntaxfouten genereren, tenzij het werd gemaakt als een “long-bracket string”—zie [Wat zijn Lua-escapesequenties](/latex/nl/diepgaande-artikelen/09-an-introduction-to-luatex-part-2-understanding-directlua.md#what-are-e2809clua-escape-sequencese2809d3f) voor achtergrond bij dat probleem.

Als we proberen te gebruiken `\codestoemoji` met een `\char` commando, zoals dit:

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

LuaHBTeX zal falen en een syntaxisfout melden, ongeveer zoiets als:

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

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

De Lua-interpreter liep tegen een probleem aan, dus het
restant van dit Lua-blok wordt genegeerd.
```

#### De HarfBuzz-vormgevingsfunctie aanroepen

**Bufferparameters instellen**

HarfBuzz heeft soms aanvullende informatie nodig over de tekst die het moet vormgeven. U kunt die informatie geven door uw `<buffer variable>` met behulp van *buffer-methoden*, zoals:

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

Bijvoorbeeld: we moeten HarfBuzz laten weten dat de richting van onze emoji-tekst van links naar rechts is. Om dat te doen, gebruiken we de `set_direction()` methode op onze `<buffer variable>` (genaamd `hbbuffer`) door te schrijven:

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

waar `hblib.Direction.new("ltr")` maakt een “richtingsobject” aan dat geschikt is om via Lua aan de HarfBuzz-engine door te geven.

**Vormgeving uitvoeren**

Nadat de buffer voldoende is geïnitialiseerd, kunnen we HarfBuzz vragen de eigenlijke vormgeving uit te voeren via de functie `shape_full()`. In ons voorbeeld schrijven we:

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

De 3e en 4e parameters van de `shape_full()` functie moeten Lua-tabellen zijn—we hebben lege tabellen “`{}`” voor beide parameters gebruikt. De algemene vorm van `shape_full()` is:

```latex
shape_full(Harfbuzz font, Harfbuzz buffer, {font features}, {"shaper"}
```

* **`{"shaper"}`**: hoeft meestal niet te worden ingesteld, maar de opties zijn `{"ot"}` of `{"graphite2"}`. Meer informatie over het concept van een “shaper” is te vinden in [de HarfBuzz-documentatie](https://harfbuzz.github.io/shaping-and-shape-plans.html)—let op: dit documenteert de low-level C-API, niet de op Lua gebaseerde `luaharfbuzz` binding (implementatie).
* **`{font features}`**: Dit is een tabel met de [OpenType-functies](https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist)—door het lettertype ondersteunde— die u HarfBuzz wilt laten toepassen tijdens het vormgeven.

Elke lettertypefunctie die u wilt gebruiken moet worden aangemaakt met behulp van een `luaharfbuzz` bibliotheekfunctie

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

waar

* `library_instance` is uw `luaharfbuzz` bibliotheekinstantievariabele (`hblib` in ons voorbeeld);
* `feature_string` gebruikt een [syntaxis om functies te definiëren](https://github.com/ufytex/luaharfbuzz/wiki/Feature-Strings). Voorbeelden hiervan zijn `+smcp` om kleinkapitalen te activeren of `-kern` om kerning uit te schakelen.

Bijvoorbeeld:

```latex
local dosmcp = hblib.Feature.new("+smcp")
local nokern = hblib.Feature.new("-kern")
% Gebruik uw lettertypefuncties zo
local res = hblib.shape_full(hbfont, hbbuffer, {dosmcp,nokern},{})
```

#### Toegang tot het resultaat: de glyphs ophalen

En tot slot: als de vormgeving slaagt, worden de gevormde glyphs teruggegeven in de buffer-variabele `hbbuffer` die we eerder in de code hebben aangemaakt.

We krijgen toegang tot de glyphs via de buffer-methode `get_glyphs()` en gebruiken een lus om elke afzonderlijke glyph op te halen. Merk op dat de Lua-tabel met de glyphs, `hbglyphs` in ons voorbeeld, wordt geïndexeerd vanaf 1, niet vanaf 0.

Van elke glyph: *glyph-id* (verwarrend genoeg genoemd `codepunt`), en het HarfBuzz-lettertype (`hbfont`), wordt doorgegeven aan de `writePNGglyph()` functie die een PNG-bestand maakt met behulp van de rasterafbeeldingsweergave van die glyph van het lettertype.

`writePNGglyph()` schrijft een PNG-bestand weg en geeft de PNG-bestandsnaam terug, die wordt gebruikt om het (geschaalde) PNG-bestand in ons LaTeX-document te importeren via `\includegraphics[scale=0.75]{<fname>}`. Merk op hoe we `\includegraphics` rechtstreeks binnen de Lua-code kunnen gebruiken.

```latex
if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % De glyphs-tabel, hbglyphs, is 1-gebaseerd
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % Verklein de grootte van onze geïmporteerde PNG-afbeeldingen
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
```

### De volledige code die u in Overleaf kunt openen

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

% Laad de luaharfbuzz-bibliotheek vanuit LuaHBTeX
hblib=require("luaharfbuzz")

% Zoek het Noto Color Emoji-lettertype op de server van Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Maak een HarfBuzz-face en HarfBuzz-font van Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% Deze functie accepteert een font en een glyph-ID:
% het extraheert de PNG-gegevens van de glyph en schrijft
% die naar een .png-bestand

function writePNGglyph(hbfontobject, glyphID)

    % Verkrijg PNG-gegevens van de glyph
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % Maak een bestandsnaam voor ons .png-bestand
    local fname="Glyph"..glyphID..".png"

    % Schrijf het .png-bestand en geef de bestandsnaam terug
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % Geef de bestandsnaam terug voor \includegraphics om te gebruiken
    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()
    % De glyph-tabel, hbglyphs, is 1-gebaseerd.
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % Verklein de grootte van onze geïmporteerde PNG-afbeeldingen
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}

Een eend: \codestoemoji{\Uchar"1F986}

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

[Open dit luaharfbuzz-API-voorbeeld in Overleaf.](/latex/nl/diepgaande-artikelen/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md)

Dit voorbeeld levert de volgende uitvoer op:

![Harfbuzzexample.png](/files/31e107c3f1b8dae036a004f88acdc5331967a027)

## Bonussectie: Plezier met emoji-wiskunde

Om luchtig af te sluiten, gebruikte een lid van het Overleaf-team de [`emoji` LaTeX-pakket](https://ctan.org/pkg/emoji?lang=en) om een leuk voorbeeld te maken:

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

[Open dit leuke voorbeeld in 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)

Dit voorbeeld levert de volgende uitvoer op:

![Emojimath2.png](/files/9c0444abc99a4a64230b0783fdb2c52360d69d29)


---

# 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/nl/diepgaande-artikelen/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.
