> 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/ja/xiang-xi-ji-shi/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md).

# LaTeXでカラー絵文字フォントの使用を支える技術の概要

## はじめに

この記事では、さまざまな項目の概要を示します [背景トピック](#which-topics-do-we-cover) この記事では、LaTeXでカラー絵文字を組版するためにOpenTypeカラーフォントを使用することに関連する、さまざまな背景トピックについて概説します。幅広い関心や専門性に対応できるよう、さまざまな資料を用意しようと努めました。記事を扱いやすくするため、いくつかのトピックについては技術的な詳細をかなり省略していますが、LaTeXでカラー絵文字を組版することを探求するうえで、十分な手がかりとなることを願っています。

**更新（2023年7月）**：この記事は2021年8月に初版が公開され、2023年7月に次のセクションを更新するために改訂されました。 [LuaHBTeXでSVGベースのOpenTypeカラーフォントを使う](#using-svg-based-opentype-color-fonts-with-luahbtex).

### どのトピックを扱うのか？

この記事では、次の一般的なトピックを扱います：

* Unicodeとは、絵文字を文字として符号化し、テキスト処理および組版アプリケーションにおける期待される振る舞いを定める標準です。
* OpenTypeカラーフォント：LaTeX文書に表示される絵文字文字を色付きで表現する特殊なフォント。
* テキストシェーピング：複雑な文字体系の言語や絵文字を組版するうえで重要な構成要素の紹介。
* HarfBuzz：LuaHBTeXの構成要素で、高度な多言語組版とOpenTypeカラーフォントを使ったLaTeXでの絵文字組版を可能にします。
* さまざまなTeXエンジン：OpenTypeカラーフォントへの対応を探り、どのTeXエンジンを使うかを選択します。
* LuaHBTeXのHarfBuzz API：「魔法」の裏側の紹介 [テキストシェーピング](#the-concept-of-text-shaping) LuaHBTeXにおける。

### カラー絵文字を組版する3つの方法

カラー絵文字はLaTeXで次の3つの主な方法で組版できます：

1. TikZ、MetaPost、Asymptoteなどの標準的なLaTeXグラフィックスツールを使って絵文字を描画する。
2. 外部ファイルに保存された、あらかじめ用意した絵文字グラフィックを挿入する。
3. 絵文字をUnicodeで符号化されたテキストとして扱い、 [テキストシェーピング](#the-concept-of-text-shaping) と [OpenTypeカラーフォント](#opentype-color-fonts) で組版する。

LaTeX文書にカラー絵文字を含める実際的な選択肢は、その文書をコンパイルするのに使うTeXエンジンによって異なります。つまり、次のいずれを使うかです：

* pdfLaTeX：pdfTeXエンジン + LaTeX；
* XeLaTeX：XeTeXエンジン + LaTeX；
* LuaLaTeX：LuaHBTeXエンジン（TeX Live 2020以降） + LaTeX。

これら3つのTeXエンジンはいずれも、LaTeXのツールやパッケージを使って絵文字を描画したり、 `\includegraphics{...}` 外部グラフィックファイルに保存された絵文字を挿入したりできます。描画やグラフィックの取り込みは、LaTeX文書のコンパイルに使うTeXエンジンに依存しない解決策が必要な場合に、絵文字を組版するのに理想的な手法です。

ただし、ワークフローにおいて特定のTeXエンジンを選べる柔軟性があり、OpenTypeカラーフォントとUnicodeベースのテキスト処理を使いたいのであれば、LuaTeXの最新版であるLuaHBTeXが必要です。TeX Live 2020以降では、LuaHBTeXがLuaLaTeX形式に基づくLaTeX文書のコンパイルに使われます。

## Unicodeと絵文字文字の背景

### 文字エンコーディング

コンピュータは、テキストを構成する *文字*という数値（整数）列を使ってテキストを保存・送信・処理します。信頼できるテキスト処理には、テキストの送受信側が、テキストストリーム内の個々の文字を表すためにどの整数値を使うべきかについて合意している必要があります。言い換えると、そのテキストの *文字* *エンコーディングとは何か？* エンコーディングとは、ある文字集合を表すために割り当てられた合意済みの整数値の集合です。各文字は、使用されているエンコーディング内の整数値1つで表されます。

### Unicodeの登場

歴史的には、8ビットのテキストの時代に、さまざまな文字エンコーディングが使われ、常に *エンコーディングの不一致*を引き起こす危険がありました。つまり、送信側と受信側が誤って異なるエンコーディングを前提にしてしまい、テキスト処理エラーが発生することです。TeX/LaTeXを何年か使ってきた人なら、入力テキストと文書を組版するためのフォントとの間でエンコーディングの不一致に遭遇したことがあるでしょう。文書フォントがテキストとは異なるエンコーディングを使うように設定されていると、組版されたPDFで文字が欠けたり誤ったりする可能性があります。

こうした歴史的なエンコーディング問題は、世界中の文字すべてを符号化する国際標準であるUnicodeを使うことで解決できます。Unicode標準は静的ではなく、エンコーディング体系に追加の文字やスクリプト（書記体系）を含めるために定期的に更新されます。新しい文字を提案するための [正式な審査プロセス](http://www.unicode.org/pending/proposals.html) と、特定の [新しい絵文字文字のための仕組みがあります。](https://www.unicode.org/emoji/proposals.html).

### Unicodeの文字は何個あるのか？

Unicodeは理論上の最大で1,114,112文字を符号化できます。1,114,112個の整数値はそれぞれ *コードポイント*と呼ばれます。これは各文字を識別するために割り当てられた整数値です。ただし、さまざまな技術的理由により、実際の文字に割り当て可能なのは [1,112,064個のコードポイント](https://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology) だけです。2048個のコードポイントは割り当て不可で、Unicode準拠のテキスト内での使用が禁止されています。

本稿執筆時点（この記事の初版時点）では、Unicode標準の第13版は実際の文字に合計143,859個のコードポイントを割り当てており、その中には [現在絵文字として符号化されている3304文字](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) が含まれます（その文書の2ページ目を参照）。Unicodeで符号化される文字数の増加は、記事 [Unicodeの文字は何個あるのか？](https://www.babelstone.co.uk/Unicode/HowMany.html) および [Wikipediaの項目](https://en.wikipedia.org/wiki/Unicode#Versions).

### Unicodeのプレーン

1,114,112個のUnicodeコードポイント全体は、17のいわゆるプレーンに分類されます。プレーン0からプレーン16まであり、それぞれ65536個のコードポイント値を含み、合計で $$17\times2^{16} = 1,114,112$$ 文字となります。プレーン0は [基本多言語面](https://en.wikipedia.org/wiki/Plane_\(Unicode\)#Basic_Multilingual_Plane)と呼ばれ、最も一般的に使われる文字を符号化します。プレーン1〜16は [補助面](http://unicode.org/glossary/#supplementary_planes).

### 絵文字の台頭

新しい文字は、人間のコミュニケーションの様式の変化によって生まれます。携帯電話技術は、そのような文字の一群である絵文字を生み出しました。絵文字は1990年代後半の日本で発展したのです。そのため、 [Unicodeの絵文字FAQ](https://unicode.org/faq/emoji_dingbats.html) に次の記述があるのも不思議ではありません。

> 「emojiという語は日本語の [絵](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E7%B5%B5) （e ≅ 画像）+ [文字](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E6%96%87) （moji ≅ 書かれた文字）に由来します。」

絵文字の背景や歴史的発展に興味のある読者には、こちらの [Unicode入門](https://unicode.org/reports/tr51/#Introduction) または記事 [I second that emoji: 絵文字の標準、構造、社会的生産](https://firstmonday.org/ojs/index.php/fm/article/view/9381).

多くの絵文字が正式に [Unicode標準6.0版](https://www.unicode.org/versions/Unicode6.0.0/)が公開されて初めて、 *文字* 独立したものとして正式に認められました。Unicode 13.0では [3304文字が絵文字として符号化されました](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) （その文書の2ページ目を参照）。Unicode 13.1では [3521個の絵文字が掲載されています](https://unicode.org/emoji/charts/emoji-counts.html).

### 絵文字はより高いプレーンに存在する

Unicodeは多くの絵文字文字を基本多言語面（BMP）外のコードポイントに割り当てており、 [プレーン1に](https://en.wikibooks.org/wiki/Unicode/Character_reference/1F000-1FFFF) コードポイント範囲1F000〜1FFFFで符号化されています。これは、 *コピー＆ペースト* した絵文字文字をOverleafのエディタ（Code EditorまたはVisual Editor）へ貼り付けたい人にとって重要な結果をもたらします。Overleafのテキストエディタは、現時点では基本多言語面内の文字しか扱えませんが、将来のアップグレードで非BMP文字への対応が導入されることを期待しています。この制限は、Overleafのエディタで編集するファイルに貼り付けられたテキスト中の非BMP文字にのみ適用されます。絵文字文字にアクセスする別の方法もあります：

* 原始コマンドを使う `\char"<コードポイント>` または `\Uchar"<コードポイント>` （ [この節](#optional-detail-luatexluahbtex-char-vs-uchar) を参照）
* 絵文字文字を含むUTF-8形式の入力テキストファイルを使う。
* 絵文字文字を挿入するLaTeXコマンド（マクロ）を使う。

#### 絵文字やその他の非BMP文字をOverleafに貼り付ける

たとえば絵文字 😀 をOverleafのCode Editorに貼り付けると、現時点では �� に変換されます。

![Overleafエディタに非BMP文字をコピー＆ペーストしたことによるエラー](/files/76a8d03ad98e7b537af6b150819a052925ce243c)

� 文字はUnicodeコードポイントFFFDを持ち、正式名称はREPLACEMENT CHARACTERで、次を「[未知、認識不能、または表現不能な文字を置き換える](https://en.wikipedia.org/wiki/Specials_\(Unicode_block\))」。

### LuaLaTeXでUnicodeコードポイント（U+）を使う

Unicodeの文書では、コードポイント値を次の表記で表します。 `U+<16進値>`—たとえば `U+1F600`、ここで `1F600` は `<16進値>` は、😀絵文字文字のUnicodeコードポイントの16進値です。LuaLaTeXでこれらのコードポイント値を使うには、 `U+` を取り除いて、次のように書きます `\char"<16進値>` または `\Uchar"<16進値>`と呼ばれます。 `"` という文字は、与えられた数値が16進数で指定されていることをTeXエンジンに知らせます。たとえば、😀絵文字を使うには、 `\char"1F600` または `\Uchar"1F600`—それを組版できるフォントを使って。

次を使った最小限のLuaLaTeX例 `\char` や `\Uchar` で😀絵文字文字を組版すると、次のようになります：

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz,SizeFeatures={Size=20}]{NotoColorEmoji.ttf}
%\emojifont はグループ内で使って効果を局所化する
{\emojifont
\Uchar"1F600
\char"1F600}
\end{document}
```

[このLuaLaTeX例をOverleafで開く](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Test+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%5D%7BNotoColorEmoji.ttf%7D%0A%25Use+%5Cemojifont+in+a+group+to+keep+its+effects+local%0A%7B%5Cemojifont+%0A%5CUchar%221F600%0A%5Cchar%221F600%7D%0A%5Cend%7Bdocument%7D)

**（補足）LuaTeX/LuaHBTeX：\char と \Uchar**

従来の `\char<文字コード>` コマンドに加えて、特定の `<文字コード>`を現在のフォントで組版するために、LuaTeX、LuaHBTeX、XeTeXエンジンには `\Uchar<文字コード>` コマンドもあります。利用者の視点では、 `\char` や `\Uchar` は同じように見えますが、下で述べるように、これらのコマンドの動作には微妙な違いがあります。

**重要な違い：展開**

`\Uchar` は、いわゆる [展開可能コマンド](/latex/ja/xiang-xi-ji-shi/22-how-does-expandafter-work-the-meaning-of-expansion.md#expansion-a-general-term-for-a-set-of-operations) であるのに対し、 `\char` は展開可能ではありません。 `\char<文字コード>` または `\Uchar<文字コード>` コマンドが「実行」されているとき、つまりマクロや他のトークン列の一部として保存されていないとき、TeXエンジン内では次の処理が行われます：

* **`\char<文字コード>`** は、TeXエンジンに対し、を表す文字トークンを直ちに挿入するよう指示します。 `<文字コード>`それを、現在組版しているどの内容にも挿入します。
* これに対し、 **`\Uchar<文字コード>`** には2つの異なる処理段階があります：

1. この `\Uchar<文字コード>` コマンドは *展開されて*、そして `<文字コード>` は、単一の [文字トークン](/latex/ja/xiang-xi-ji-shi/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#tex-tokens-101-28and-notions-of-expansion29) を含む一時的なトークン列に変換されます。これは `<文字コード>`.
2. その1文字のトークン列は現在 *利用可能にされ* 、次の入力の स्रोतとしてTeXエンジンに提供されます。実質的には、TeXエンジンは「一時的に視線を移し」、その単一トークン列を次の入力項目（トークン）の場所として使います。既定では、TeXエンジンは単にそのトークンを読み戻して（入力して）対応する文字を組版し、 `\char` コマンド。 **しかし**、その `<文字コード>` がただちに組版されるのではなく、一時的に *格納* 単一トークンとして（保存）されたため、原始TeXコマンドやLaTeXマクロはそのトークンを利用（吸収）できます。すぐに組版する必要はなく、必要に応じて後続の処理に使えます。

実質的には、 `\char<文字コード>` は「これを `<文字コード>` 今すぐ組版せよ」と言う `\Uchar<文字コード>` は、保存された文字トークンを作成して次の入力項目（トークン）として利用可能にすることで、一種の「遅延動作」を行います。そのトークンは、TeXコマンドやマクロに利用（吸収）されることも、TeXエンジンによって再読込されて組版されることもあります。

### Unicode（エンコーディング）だけがすべてではない

Unicodeで符号化されたテキスト内で絵文字文字を使えることは、絵文字成功の物語の一部にすぎません。絵文字の利用拡大は、 [OpenTypeフォント技術](https://learn.microsoft.com/en-us/typography/opentype/)—グリフデータ（文字デザイン）に [カラー情報](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)を含められるフォント—、いわゆる [OpenTypeカラーフォント](#opentype-color-fonts).

適切なフォントに加えて、カラー絵文字の利用には追加のソフトウェア構成要素が必要で、その役割には次のものが含まれます：

* 前処理（「[シェーピング](#the-concept-of-text-shaping)」）されたUnicodeテキスト、 *を表示用に準備し、* 特定のフォントを使って表示できるようにすること；
* *レンダリングと表示* フォントの色付き絵文字の *グリフ* をデバイスの画面に出力すること。

#### グリフと文字：同じものではないのか？

「グリフ」と「文字」という用語は、同じ基本概念を指すものとして互換的に使われがちですが、その意味には微妙ながら重要な違いがあります。

Unicode [は「character」という用語を](http://www.unicode.org/glossary/#character) 次のように定義しています：

> 「意味的価値を持つ書かれた言語の最小構成要素。特定の形ではなく、抽象的な意味および／または形状を指す…」

これに対し、「glyph」は *特定の* *シェイプ* （デザイン）であり、 *視覚的表現* を表す *文字*.

文字とグリフの違いは、絵文字を多く含むテキストをさまざまなソフトウェアシステム／プラットフォームで表示したときに、たとえばiOSやAndroidのスマートフォン、あるいはWindowsのデスクトップコンピュータで同じテキストを読んだときに、容易に観察できます。どのデバイスやプラットフォームを使っても、基礎となるテキスト（文字の並び）には同じUnicodeで符号化された *絵文字* *文字*が含まれています。 *前処理* がそのテキストを *レンダリングし* や *表示* その結果を、場合によってはデバイス固有のフォントを使って表示するため、同じ絵文字文字を表す異なるグリフ（文字デザイン）が生成されます。

Unicodeの [絵文字一覧](https://unicode.org/emoji/charts/full-emoji-list.html) は、各Unicode絵文字文字を表すサンプル画像を提供しており、さまざまな技術ベンダーが使う多様なグリフを示しています。フォント設計者は絵文字文字を表すために独自のデザイン（グリフ）を採用するだけでなく、個々のフォントが対応する（グリフを含む）絵文字文字の数も異なり、Unicodeの絵文字仕様に含まれる、より高度な絵文字テキスト処理機能を備えている場合もあれば備えていない場合もあります。

文字という概念、その意味論と符号化はUnicodeの世界の基盤を成しています。Unicodeは文字を扱うのです。個々の文字のデザインと視覚的表現は、グリフとしてはフォント技術とフォント設計の領域に属します。

#### Unicodeの絵文字：単なるテキストエンコーディング以上のもの

Unicodeの中心的役割は、グローバルなエンコーディング標準を提供し、 *コードポイント、* と呼ばれるどの整数値を、Unicodeで符号化されたテキストストリーム内で各文字を表すために使うべきかを定義することです。

Unicodeの絵文字仕様では、さらに *処理動作* が、Unicodeで符号化されたテキストストリーム内に現れる絵文字文字の *連続した文字列* 特定のものについて定義されています。定義された絵文字文字のシーケンスは、 [テキストシェーピング](#the-concept-of-text-shaping) というプロセスによって「結合」され、1つの結果的な（「合成」）絵文字グリフを生成できます。その単一のグリフは、デバイスのオペレーティングシステムによって、テキスト中にある元の文字列を表すために使われます。

Unicodeの技術報告書 [Unicode絵文字](https://unicode.org/reports/tr51/) は、Unicode準拠の絵文字文字処理を提供したいソフトウェアが利用できる豊富な機能セットを文書化しています。例として、Unicodeは次のような文字を定義（符号化）しています。 [絵文字修飾子](http://www.unicode.org/reports/tr51/#Emoji_Modifiers_Table) を使って生成できる *バリエーション* 、たとえば次のような「基本」絵文字文字の [フィッツパトリックスケールに基づく肌の色の違い](http://www.unicode.org/reports/tr51/#Diversity)。基本絵文字文字の集合と適用可能な修飾子は、全体としての [Unicode絵文字標準](http://www.unicode.org/reports/tr51).

Unicodeのページ [Emoji Sequences](http://unicode.org/emoji/charts/emoji-sequences.html) は、現在Unicode仕様で提供されているシーケンスの一覧表を示しています。絵文字グリフの画像の上にマウスポインタを置くと、そのグリフを生成する基礎となるUnicode絵文字文字列を示す小さなポップアップツールチップが表示されます：

![EmojiSequenceChart.png](/files/10e30cb5297a95420c2e852b6135790d5db8e96e)

たとえば、次の絵文字グリフ：

![HandMediumSkinTone.png](/files/669d710f534a85c67f047a37f3c67c688c8fdecc)

は [修飾子シーケンスの節](http://unicode.org/emoji/charts/emoji-sequences.html#modifier_sequences) に掲載されており、2文字のシーケンス U+1F44B U+1F3FD によって生成されます。構成文字は次のとおりです：

U+1F44B：![UnicodeWavingHandDefault.png](/files/85e59134575a494d187dd94a07a0f58b704fba96) （WAVING HAND）

U+1F3FD：![FitzPatrick3.png](/files/cde7a18ab52e95b80cf8220859847c7b4ce6ac40) （EMOJI MODIFIER FITZPATRICK TYPE-4）

**LuaHBTeXで肌色修飾子を使う**

次の例ではLuaHBTeXを使って、絵文字修飾子の使用を示します：

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=HarfBuzz,SizeFeatures={Size=20}]{NotoColorEmoji.ttf}
単独の手を振る絵文字：{\emojifont\Uchar"1F44B}\par
単独の修飾子：{\emojifont\Uchar"1F3FD}\par
結合結果：{\emojifont\Uchar"1F44B\Uchar"1F3FD}
\end{document}
```

[このLuaLaTeXの絵文字修飾子例を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)

この例では次の出力が生成されます:

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

#### UTF-8：Unicodeテキストの保存における役割

OverleafのCode Editor（またはVisual Editor）に入力または貼り付けるテキストやコードは、UTF-8形式で保存されるため、UTF-8の実際の意味を簡単に確認します。UTFはUnicode Transformation Formatの略で、Unicodeで符号化されたテキストを保存または送信するUTF-8の役割は、「Transformation *Format*」によって示されます。

Unicodeのコードポイント値は0から最大1,114,111まであるため、256種類までしか格納できない単一の8ビットバイト（0〜255）だけでUnicode文字値のすべてを表すことはできません。しかし、任意のUnicodeコードポイント整数は *連続した並び* のバイトサイズ値で表すことが可能です。これがUTF-8の基本原理です。

UTF-8は *変換* （つまり「符号化」または「変換」する）Unicodeの整数コードポイント値を、1〜4個の連続したバイトサイズ整数の一意な並びに変換する「レシピ」を提供します。必要な連続バイト数はコードポイント整数の値によって異なります。そのため、UTF-8がUnicode文字を保存するときは *マルチバイト列* と表現されることがあります。これは、1つのUnicode文字（コードポイント整数）がUTF-8では1〜4個の連続バイトの並びとして表されるためです。

もちろん、UTF-8で保存されたテキストは元のUnicodeコードポイント整数列に戻すことができます。UTF-8形式で保存されたLaTeX入力ファイルを読み込むときに、XeTeXやLuaTeX/LuaHBTeXが行うのはこれです。これらのTeXエンジンは、テキストを組版する前に入力Unicodeコードポイント（文字）値を知る必要があります。なお、pdfTeXにはUTF-8のデコード機能が組み込まれていないため、UTF-8で書かれた入力テキストを処理（デコード）するにはTeXマクロに頼る必要があります。

**UTF-8の例**

* アラビア文字 ش（「sheen」）のUnicodeコードポイントは、16進数（基数16）で0634、10進数（基数10）で1588です。UTF-8では ش は2つの16進値 D8 と B4 で表されるため、文字 ش はUTF-8で符号化されたテキスト内では連続する2バイト D8B4 として保存されます。
* 絵文字 😀 のUnicodeコードポイントは、16進数（基数16）で1F600、10進数（基数10）で128512です。UTF-8では 😀 は4つの16進値 F0、9F、98、80 で表されるため、文字 😀 はUTF-8テキストファイル内では連続する4バイト F09F9880 として保存されます。

#### Unicodeベースの絵文字テキスト処理で使われる特殊文字

Unicodeで符号化されたすべての文字が、フォント内のグリフを通じた視覚的表示を意図しているわけではありません。符号化された文字の中には次のように指定されるものがあります。 *非印字文字* その目的は、（対応ソフトウェア内の）特殊なテキスト処理機能を補助することです。Unicodeに符号化された非印字文字への対応度はソフトウェアによって異なるため、結果は使用しているソフトウェア環境—アプリケーションとフォント—に依存します。

**知っておきたい2つの非印字文字**

* **ゼロ幅接合子（ZWJ）**&#x306F;、コードポイント200D（16進数）で、その名が示すとおり、入力文字の「接合動作」を引き起こすよう設計されています—ただし、それは入力文字が *持っている場合に限られます。* 定義された接合動作を。
* **ゼロ幅非接合子（ZWNJ）**&#x306F;、コードポイント200C（16進数）で、 *防ぎたい* 入力文字が本来示す可能性のある「接合動作」を抑制するよう設計されています。たとえば、ZWNJを使うと、通常は接合形に処理（シェーピング）される連続したアラビア文字の接合動作を防ぐことができます。

Unicodeは次の一覧を公開しています。 [推奨される絵文字ZWJシーケンス](https://unicode.org/emoji/charts/emoji-zwj-sequences.html) これらはU+200D ZERO WIDTH JOINER（ZWJ）を使って絵文字文字列を1つの合成絵文字グリフに結合します—使用しているフォントにそのグリフがあれば。

**ゼロ幅非接合子の使用例**

次の最小コード断片では、TeX Liveに含まれるScheherazade OpenTypeフォントを使って、次の名前のLaTeXフォントを定義します。 `\arabicfont` このフォントを使ってアラビア語をいくらか組版できます。次の行

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

では、次を介してゼロ幅非接合子を使っています。 `\Uchar"200C`これにより、アラビア文字 ل（lam）と ا（alef）の通常の接合動作を防ぎます。 `\textdir TRT` を使って、文字方向を右から左に設定している点に注目してください：

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

[このLuaLaTeX例をOverleafで開く](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Zero+width+non-joiner+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Carabicfont%5BScript%3DArabic%2CRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D40%7D%5D%7BScheherazade%7D%0A%7B%5Carabicfont+Joining%3A%5Ctextdir+TRT%5CUchar%220644%5CUchar%220627%7D%5Cpar%0A%7B%5Carabicfont+Non-joining%3A%5Ctextdir+TRT%5CUchar%220644%5CUchar%22200C%5CUchar%220627%7D%0A%5Cend%7Bdocument%7D)

この例では次の出力が生成されます:

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

## 「テキストシェーピング」の概念

「educational」のウルドゥー語訳を使った視覚的な例から始めましょう。ウルドゥー語訳のテキストはキーボードやタッチスクリーン端末で入力され、単純な直線状のUnicodeアラビア文字列として作成されます。しかし、そのテキストが組版されたり、デバイス画面に [ナスタアリーク体](https://en.wikipedia.org/wiki/Nastaliq)で表示されたりすると、結果はグリフの複雑な二次元配置になります。

このウルドゥー語の例では、次の図がUnicodeアラビア文字の直線的な入力と *文字* ナスタアリーク体で組版された出力を比較しており、 *グリフ* （無料の）フォント [Awami Nastaliq](https://software.sil.org/awami/download/):

![](/files/67d1891fd9b7168abfc6d68da709d0a7f14e70c4)

入力文字を正しい位置に配置された出力グリフ群へ「変換」する処理は *テキストシェーピング*シェーピングと呼ばれ、表示や組版の前にテキストを処理するうえで不可欠な要素です。ここでウルドゥー語（アラビア文字）を例にしたのは、シェーピングの結果がはっきり見えるからで、英語のようなラテン文字を使う言語では、単純な合字の生成など、シェーピングはそれほど顕著ではありません。

テキストシェーピングは、 [アラビア語](https://en.wikipedia.org/wiki/Arabic), [ヘブライ語](https://en.wikipedia.org/wiki/Hebrew_language), [デーヴァナーガリー](https://en.wikipedia.org/wiki/Devanagari) または [マラヤーラム語](https://en.wikipedia.org/wiki/Malayalam)は、いわゆる *複雑な文字体系*の4例にすぎません。これらの文字体系と、それを使う言語でテキストを正しく表示するには、シェーピング処理がその文字体系と言語の組み合わせに存在するあらゆるシェーピング規則やニュアンスを慎重に扱う必要があります。たとえば、特定の出力グリフを生成するのに複数の入力文字が必要な言語もあれば、ダイアクリティカルマークの慎重な配置や、グリフ同士の相対的位置を正しく保つための並べ替えが複雑に求められる場合もあります。

一般に、テキスト片をシェーピングするには、いくつかの情報が必要です：

* 書記体系または *文字体系* テキストが書かれているもの。
* 特定の *言語* 使用されているもの。個々のスクリプトは複数の言語で使用されることがあり、スクリプトと言語の各組み合わせにはそれぞれ独自の整形上の微妙な違いやニュアンスがあります。
* 書字の *方向* テキストの—右から左、または左から右など。
* ある *フォント* 整形済みテキストを表現するのに必要なグリフを提供し、必要に応じてテキスト整形処理を導く追加の「整形ルール」も含む。

テキスト整形の要件、特に複雑なスクリプトとそれに関連する言語については、非常に詳細でニュアンスに富む場合があり、潜在的に非常に複雑なテキスト整形の「ルール」を適用できる専門ソフトウェアの必要性を示しています。驚くことではありませんが、そのようなソフトウェアは存在し、 *テキスト整形エンジン*と呼ばれます。ここで取り上げるものは [Harfbuzz](https://en.wikipedia.org/wiki/HarfBuzz)と呼ばれるもので、そのドキュメントは読む価値があります。たとえば [なぜ整形エンジンが必要なのか？](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html).

**テキスト整形についてのさらに詳しい読み物**

以下の短い入門記事を強くおすすめします：

* [テキスト整形とは何か？](https://harfbuzz.github.io/what-is-harfbuzz.html#what-is-text-shaping)
* [なぜ整形エンジンが必要なのか？](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html)

**TeX的注記：複数の整形技術（モデル）**

HarfBuzzテキスト整形エンジンはいくつかの「整形技術」をサポートしており、それらは整形処理の実装方法が異なります。各実装は *シェーパー*と呼ばれます。 `luaotfload` のドキュメントでも使われています。この記事の主な焦点はOpenType整形ですが、別の無償で使える技術として [Graphite](https://scripts.sil.org/cms/scripts/page.php?site_id=projects\&item_id=graphite_aboutOT)があり、これは [SIL International](https://www.sil.org/)によって開発されました。HarfBuzzがサポートする別の整形モデルは [Apple Advanced Typography (AAT)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html)です。AATをサポートするフォントは、一般にAppleの技術プラットフォームで使用されます。

**Graphiteシェーパーを使った例**

次の例では、というフォントを使ってウルドゥー語のテキストを組版します。 [Awami Nastaliq](https://software.sil.org/awami/download/)これはGraphite整形をサポートしており、Overleafで利用できます。Awami Nastaliqは [SIL International](https://www.sil.org/)によって作成されました。Graphite技術の開発を担う組織です。

次の例は、Graphiteベースのフォントの高度な整形能力を示しています。 `luaotfload` フォント宣言が次の指定でGraphite整形を選択している点に注目してください。 `shaper=graphite2`.

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

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

\\vskip 75bp

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

[この例を Overleaf で開く。](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+Urdu+using+the+Graphite+shaper\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bluaotfload%7D%0A%5Cbegin%7Bdocument%7D%0A%0A%5Cfont%5Curdutest%3D%7Bfile%3AAwamiNastaliq-Regular.ttf%3Amode%3Dharf%3Bshaper%3Dgraphite2%7D+at+100bp%0A%25+Technology%0A%5Cpardir+TRT%5Ctextdir+TRT+%5Curdutest+%D9%B9%DB%8C%DA%A9%D9%86%D8%A7%D9%84%D9%88%D8%AC%DB%8C%0A%0A%5Cvskip+75bp%0A%0A%25+Educational%0A%5Cpardir+TRT%5Ctextdir+TRT+%5Curdutest+%D8%AA%D8%B9%D9%84%DB%8C%D9%85%DB%8C%0A%5Cend%7Bdocument%7D)

この例では次の出力が生成されます:

![](/files/4be99b711354b47f5b2f0c533449a2233ff1ecf5)

#### 絵文字とテキスト整形

テキスト整形は、複雑なスクリプト言語であるウルドゥー語の例を用いて導入されました。しかし、正しい絵文字グリフをレンダリングするには、絵文字文字の並びを含むUnicodeテキストにテキスト整形を適用する必要があると知ると驚くかもしれません—[HarfBuzzの主任開発者が述べているように](https://github.com/harfbuzz/harfbuzz/issues/2428#issuecomment-639108677):

> ...HarfBuzzで絵文字を整形することは完全に対象範囲内であり、家族絵文字や肌の色などを得るために実際に必要です。

その例を見ていきます。

### 責任の分担：テキスト整形エンジン + OpenTypeフォント

実際には、テキスト整形は、テキスト整形エンジンに組み込まれたロジックとルール、および使用されるフォントに組み込まれた追加の整形ルールとデータとの間の「共同作業」、あるいは分業です。ここからはOpenTypeベースの整形のみを扱います *のみ*.

整形を行うには、テキスト整形エンジンには通常、いくつかのUnicodeテキスト、指定されたスクリプトと言語、場合によっては書字方向、そして何よりも、整形処理で使用するOpenTypeフォントが与えられます。フォントは出力として、グリフの集合と位置情報を提供します。要求に応じて、整形エンジンは追加のルール（[OpenType機能](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features)）を使用中のOpenTypeフォントに含まれるものとして適用できます。どのルールを適用するかは通常、フォントがサポートする機能一覧からユーザーが選択できます。

整形処理の結果は *グリフの一覧* であり、OpenTypeフォントに含まれる *グリフ間* の位置情報も伴います。その位置情報は *整形されたグリフ同士の相対的な配置*に関するものであり、組版されたページ内や、Webページ、ツイートなど他の媒体・コンテンツ内での絶対位置を指すものではありません。レンダリングソフトウェア（組版エンジン、Webブラウザなど）は、グリフ同士の位置情報を使って、グリフが組み合わされ最終出力に組み込まれた後も互いに正しく配置されるようにします。

#### グリフの一覧とは何か？

内部的には、OpenTypeフォント内の各グリフには数値識別子が割り当てられます。これはグリフインデックスと呼ばれる整数値で、グリフ識別子、またはGIDとも呼ばれます。整形作業を終えると、テキスト整形エンジンは結果を *グリフ識別子の一覧* と *位置情報* として返します。

OpenTypeフォント内の個々のグリフには、フォントの作成者によってインデックス（識別子）が割り当てられており、非常にフォント固有で任意の値になります。これは特定のフォントのバージョン間でも異なることがあります。異なるフォントの「似た」グリフに同じGID値が適用されると決して思ってはいけません。ほぼ確実にそうはなりません。整形エンジンが提供するグリフ識別子の一覧を持っている場合、それらは取得元のフォント内のグリフにアクセスするためにのみ使えます。

#### OpenTypeフォントとは何か？

Web上には *あふれています* OpenTypeフォントの説明や詳細が満ちあふれているので、ここでは短い説明にとどめます。 [OpenType仕様](https://docs.microsoft.com/en-us/typography/opentype/spec/) は開発者向けに設計された複雑な文書ですが、本質的にはフォントデータのファイル形式、つまりコンテナを定義しています。OpenTypeフォントには、グリフ形状を記述するデータに加え、サポートするスクリプトや言語に関する情報、フォントのメタデータ、および [組版機能](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features) を定義するさまざまな「テーブル」が含まれています。

テキスト整形エンジンには通常、整形処理中にフォントの機能を選択的に適用（使用）するよう指示できます。これにより、フォント内の適切なグリフ集合を選び出す特定の組版効果（「ルール」）が適用されます。選択したフォントは、テキスト整形エンジンが適用するよう求められたあらゆる機能をサポートし、そのためのグリフを提供する必要があります。

#### 符号化された「グリフ」と符号化されていない「グリフ」

OpenTypeフォントには、というデータテーブルが含まれています。 [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) （Character to Glyph Index Mapping）これは、フォントがサポートするUnicode文字の集合を、そのフォント内の対応するグリフインデックスに対応付けます。次の動画では、というフォントに含まれるcmapテーブルを簡単に紹介しています。 `lmmono10-regiular.otf` （TeX Liveに含まれています）。

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

しかし、フォントには通常、特定のUnicode文字を表さず、そのcmapテーブルの一部としては含まれない多数のグリフが含まれています。その結果、OpenTypeフォント内に存在するグリフの集合は、主に次の2つに分けられます。

* Unicode文字を表す符号化されたグリフ。
* Unicode文字を表さない符号化されていないグリフ。

符号化されたグリフは、テキスト中に適切なUnicode文字を含めることでアクセスできます—では、符号化されていないグリフはどうでしょうか、どうやって使う／アクセスするのでしょうか？ それらのグリフは通常、特定の視覚的・組版的効果を得るためにフォント機能を適用することを含む、テキスト整形操作の出力として使われます。

### OpenTypeカラーフォント

絵文字文字はフルカラーで表示／レンダリングされることが期待されています—白黒の絵文字では「完全な絵文字体験」とは言えません。しかし、Unicodeが絵文字を最初に符号化した時点では、 [OpenTypeフォント仕様](https://docs.microsoft.com/en-us/typography/opentype/spec/) には、埋め込むための適切な規定がありませんでした *colorful*-グリフデータをOpenTypeフォント内に埋め込むためのものです。OpenTypeのこの「空白」により、主要な技術／プラットフォームベンダーは解決策を探すようになり、その後の「競争」の結果、 [OpenTypeを拡張するさまざまな提案が生まれ](https://www.fontlab.com/news/color-font-format-proposals/) 、OpenTypeカラー・フォントをサポートするようになりました。これは色付き絵文字文字（グリフ）を表示するためだけでなく、あらゆるグリフをカラーでレンダリングするためでもあります。

#### OpenTypeカラー・フォントの4つの種類

[Adobe、Microsoft、Google、Appleはそれぞれ提案を提出し](https://www.fontlab.com/news/color-font-format-proposals/) 、OpenTypeを拡張してフルカラーのOpenTypeフォントをサポートし、最終的に4つの提案が採用され正式なOpenType仕様に含まれました。便宜上、これら4つの方式は大まかにベクターベースとラスターベースに分けられますが、この [GitHubリポジトリ](https://github.com/simoncozens/test-fonts)に示すように、OpenType仕様はそれら4つの基本技術を組み合わせたOpenTypeカラー・フォントファイルをサポートできるほど柔軟です。

* **ベクターベースのOpenTypeフォント：**
* **Microsoft**：グリフ形状は、重ね合わせた色付きベクターの形式（[COLR](https://docs.microsoft.com/en-us/typography/opentype/spec/colr) や [CPAL](https://docs.microsoft.com/en-us/typography/opentype/spec/cpal) テーブル）を用いて記述されます。
* [**AdobeとMozilla**](https://www.w3.org/2013/10/SVG_in_OpenType/) ([SVGテーブル](https://docs.microsoft.com/en-us/typography/opentype/spec/svg)）：グリフ形状はSVGを用いて描画されます。SVGはベクターから構成されたグリフをサポートし *、ラスタ画像も*ます。関連情報として [AdobeのSVGフォントに関するユーザーガイドもご覧ください](https://helpx.adobe.com/fonts/user-guide.html/fonts/using/ot-svg-color-fonts.ug.html).
* **ラスターベースのOpenTypeフォント：**
* **Google**：グリフは、フォント内に埋め込まれたカラーPNG画像で表現されます（[CBDT](https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt) や [CBLC](https://docs.microsoft.com/en-us/typography/opentype/spec/cblc) テーブル）を用いて記述されます。
* **Apple**：グリフも、フォント内に埋め込まれたカラー画像で表現されます。PNGに加えて、Appleの仕組み（[sbixテーブル](https://docs.microsoft.com/en-us/typography/opentype/spec/colr)）はJPEGとTIFFもサポートしています。

その結果、OpenTypeカラー・フォントをサポートするオペレーティングシステムやアプリケーションソフトウェアは、今日の混在した技術環境に対処する必要があります。さらに、個々のOpenTypeカラー・フォント、そして *バージョン* は、同じフォントの—

* 完全なセットに対するカバー範囲が異なり [Unicode絵文字文字](https://unicode.org/emoji/charts/emoji-list.html)—つまり、そのフォントがいくつの絵文字文字に対してグリフを提供しているか；
* 個々の絵文字文字を表すために異なるグリフデザインを使用する；
* Unicode標準のより高度な用途をサポートするために提供する機能が異なり、たとえば [絵文字修飾子](https://unicode.org/reports/tr51/#Emoji_Modifiers_Table)、およびその他の絵文字テキスト処理機能が含まれます。 [Unicode技術標準 #51: Unicode Emoji](https://unicode.org/reports/tr51/).

#### HarfBuzzをめぐる話題

私たちは、 *テキスト整形エンジン*：特定のスクリプトと言語の組み合わせで書かれた入力Unicodeテキストを受け取り、指定されたフォントを使って、そのテキストを位置情報付きのグリフ列に整形し、元の入力テキストを組版するために使えるソフトウェアです。

[HarfBuzz](https://harfbuzz.github.io/) はそのようなテキスト整形エンジンの一つです。それは [オープンソースのコードライブラリであり](https://github.com/harfbuzz/harfbuzz) 、10年以上にわたる研究開発の成果であり、今なお多くのソフトウェア製品の一部として活発に開発・展開されています。HarfBuzz自体は「組版」を行わず、それを統合することを選んだソフトウェアに「テキスト整形サービス」を提供します。これにはXeTeX、LuaHBTeX、 [Adobe PhotoShop、Adobe InDesign](https://en.wikipedia.org/wiki/HarfBuzz).

HarfBuzzを組み込むことで、TeXエンジンはその高度なテキスト整形能力を活用し、非常に洗練された多言語組版を実現できます。特に、アラビア文字、ヘブライ文字、デーヴァナーガリー文字など多くの複雑なスクリプトに有効です。また、HarfBuzzはUnicode絵文字テキスト文字の処理と整形にも使われており、これについては後ほど詳しく見ていきます。

次の図は、アラビア語のような複雑なスクリプトのテキストを組版する際に、XeTeXやLuaHBTeXなどのソフトウェアと統合されたときにHarfBuzzが果たす役割を要約したものです：

![HarfBuzzによるアラビア語テキスト整形の概要](/files/ffaa723813d80605253ecfac227272e49a173e95)

**HarfBuzzを探る**

HarfBuzzと、XeTeXおよびLuaHBTeXに提供されるOpenType整形サービスについてさらに学びたい方は、 [HarfBuzzのバイナリ配布版をダウンロードできます](https://github.com/harfbuzz/harfbuzz/releases) 。これにはHarfBuzzライブラリ（プログラマー向け）とコマンドラインユーティリティが含まれています `hb-view` や `hb-shape`.

**例：hb-viewの使い方**

お好みのUTF-8対応テキストエディタで新しいファイルを作成し、次の6つの絵文字 👋👋🏻👋🏼👋🏽👋🏾👋🏿 をそのテキストファイルにコピー＆ペーストしてから、UTF-8形式で、たとえばという名前のファイルとして保存します。 `emoji.txt`.

テキストエディタがカラーグリフをレンダリングできないため、絵文字の（フォールバックとしての）白黒版が表示されるかもしれないことに注意してください。これら6つの絵文字を保存すると、ファイル `emoji.txt` には、次のUnicode絵文字文字の並びに対応するUTF-8データが含まれているはずです。絵文字修飾子は、 *読みやすさのためだけに*:

* `1F44B` を生成します
* `1F44B`, `1F3FB` を生成します
* `1F44B`, `1F3FC` を生成します
* `1F44B`, `1F3FD` を生成します
* `1F44B`, `1F3FE` を生成します
* `1F44B`, `1F3FF` を生成します

合計で **11** 個のUnicode文字があり、それぞれが4バイトのUTF-8データを生成するため、結果として `emoji.txt` ファイルのサイズは44バイトになるはずです。絵文字を含む行の末尾に使用される行末マーカーは除きます。

この `hb-view` ユーティリティはファイルを使用できます `emoji.txt`。さらに、次のような適切なOpenTypeカラー・フォントを任意に組み合わせて使用し、 `NotoColorEmoji.ttf`を使って、HarfBuzzの整形結果のSVGファイルを生成できます。次のコマンドライン例は、 **1行で入力しなければなりません** 。端末で入力すると、SVGファイル `emoji.svg`:

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

正常に実行されると、ファイル `emoji.svg`が `hb-view`によって生成され、Inkscapeで開くことができ、次のような見た目になるはずです：

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

`hb-view` は、適切なUnicodeテキストファイルとOpenTypeフォントであればどれでもHarfBuzzの整形を調べるために使えます。絵文字に限られません！次を入力してください

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

と入力すると、この強力で便利なユーティリティの豊富なコマンドラインオプションが表示されます。楽しく整形しましょう！

## テキスト整形とTeXエンジン

ここでは、XeTeXとLuaTeX系TeXエンジンのテキスト整形機能を見ていきます。

### XeTeX

XeTeXは2000年代初頭に開発され、TeXベースの組版におけるいくつかの革新的機能の先駆けとなりました。最も注目すべきは *組み込みの* サポートです：

* UTF-8形式のUnicodeテキストの読み込み；
* OpenTypeフォントの使用；
* 多言語組版のためのテキスト整形；
* OpenTypeベースの数学組版。

XeTeXが複雑なスクリプト言語を容易かつ便利に組版できるのは、組み込みのテキスト整形機能のおかげです。これは当初、現在では非推奨となった [ICU LayoutEngine](http://userguide.icu-project.org/layoutengine)に基づいていました。Khaled Hosnyの作業により、XeTeXはテキスト整形にHarfBuzzを使用するよう切り替わりました。これは次の発表で述べられています。 [2013年3月](https://tug.org/pipermail/xetex/2013-March/024118.html)。多言語テキストを組版したい人にとって、XeTeXは通常、選択すべきTeXエンジンとして挙げられます。しかし今では、LuaHBTeXという別の選択肢があり、これを見ていきます。

### LuaTeXとLuaHBTeX

LuaTeXの開発は2005年頃に始まりましたが、新機能を *直接* XeTeXソフトウェアに組み込むXeTeXとはかなり異なる設計思想に従いました。XeTeXとは対照的に、LuaTeXの開発者は「…最小限のツールのみを提供し、解決策は提供しない。」という方針を採りました（ [LuaTeXのリファレンスマニュアル](https://www.pragma-ade.com/general/manuals/luatex.pdf)を参照）。追加機能の一式を提供するのではなく *に組み込まれた* LuaTeXベースのエンジンでは、内部機構が開放されており、開発者や熟練ユーザーが統合されたLuaスクリプト言語を利用して独自の解決策を構築できます。

たとえば、XeTeXとは異なり、LuaTeXエンジンは *直接* OpenTypeフォントを使用できません。代わりに、OpenTypeフォントはLuaコードで書かれたフォント読み込み関数を通じて読み込まれ、「使用できるように準備」されなければなりません。これらのフォント読み込み関数は *コールバック* 関数と呼ばれます。LuaTeXがフォント読み込み要求を受けたときに呼び出し（「実行」）するLuaコードです。

さらに、LuaTeXエンジンは *組み込みの* テキスト整形機能を提供しません。そうした機能も、LuaTeXエンジンが呼び出してテキスト整形サービスを提供させる外部コードによって与えられる必要があります。これも、コアソフトウェア内にテキスト整形機能を組み込んでいるXeTeXエンジンとは対照的です。

#### luaotfload：LuaTeX/LuaHBTeXでOpenTypeフォントを使うために必須

LuaTeXのフォント読み込み用コールバック機構は、追加のプログラミングという「コスト」はあるものの、非常に高い柔軟性を提供します。LuaLaTeXユーザーにとって幸いなことに、TeXコミュニティはというパッケージを開発しました `luaotfload`luaotfload [TeX Liveの毎年のリリース](https://www.tug.org/texlive/) の一部を構成し、もちろんOverleafユーザーも利用できます。

`luaotfload` は [CTAN で入手できます](https://ctan.org/pkg/luaotfload?lang=en) であり、 [GitHubに開発リポジトリがあります](https://github.com/latex3/luaotfload) 。そこで最新の開発状況や [新リリース](https://github.com/latex3/luaotfload/releases).

`luaotfload` を追うことができます。

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

次の点に注意してください `luaotfload` はLaTeXの *パッケージ*という名前です。つまりファイル名は `luaotfload.sty`です。もし `luaotfload` をplain TeXで使いたいなら、次の行を追加すればできます。

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

をplain TeX文書に。

通常、LuaLaTeXのユーザー、つまりLuaTeX/LuaHBTeXを使ってLaTeXを組版する人は、luaotfloadに直接触れる必要はありません `luaotfload` いません。なぜなら [`fontspec` パッケージ](https://ctan.org/pkg/fontspec) LuaLaTeXが `luaotfload` パッケージを読み込み、ユーザーレベルのコマンドを通じて多くの低レベル詳細を処理してくれます。 `fontspec` xr

### LuaHBTeX：テキスト整形の新しいオプション

`luaotfload` は、LuaTeXによるOpenTypeフォントの扱いを提供する成熟した強力なLuaライブラリであり、さまざまな言語やスクリプトに対するテキスト整形サービスも提供します。もともと、luaotfloadのテキスト整形関数は `luaotfload` 純粋なLuaコードで実装されていましたが、TeX Live 2020のリリースにより、テキスト整形の別の主流オプションであるLuaHBTeXという新しいLuaTeXベースのエンジンが登場しました。

LuaHBTeXの「HB」はHarfBuzzを表します。要するに、LuaHBTeXは元のLuaTeXエンジンに *と* 統合されたHarfBuzzテキスト整形エンジンを加えたものです。LuaTeXの設計思想に従い、HarfBuzzが利用可能だからといって *自動的に* LuaHBTeXがテキストを整形するとは限りません。HarfBuzzはテキスト整形ソリューションを構築するために使える別のツールです。

LuaHBTeXにおけるHarfBuzzの統合は [Luaコードでプログラム可能で](#introduction-to-the-luahbtex-harfbuzz-api)、それにより `luaotfload`の開発者はHarfBuzzベースのテキスト整形ソリューションを追加できるようになりました。その結果、 [2019年11月5日にリリースされたバージョン3.1以降](https://github.com/latex3/luaotfload/releases/tag/v3.1), `luaotfload` はHarfBuzzを活用するよう強化され、一般ユーザーがHarfBuzzのテキスト整形機能に簡単にアクセスできるようになりました。

LuaTeXへのHarfBuzz統合の技術的詳細に興味のある読者は、この [Khaled Hosnyによる論文](https://www.tug.org/TUGboat/tb40-1/tb124hosny-harfbuzz.pdf).

### luaotfload：テキスト整形の2つのオプション（HarfBuzzを使うべき時は？）

LuaLaTeXユーザーには現在、テキスト整形に2つの選択肢があります：

* `luaotfload`の元の（ノードベースの）テキスト整形実装。純粋にLuaで書かれています；
* `luaotfload`のHarfBuzzベースの整形。LuaコードがHarfBuzzのテキスト整形関数を呼び出してアクセスします。

`luaotfload` は、これら2つの整形システムへのアクセスを「`mode`」パラメータを通じて提供します—ただし、ほとんどのユーザーは同等の `fontspec` “`Renderer`」オプションを直接使い、の下位レベル関数を使うことはあまりありません `luaotfload`.

のそれぞれ `luaotfload`のテキスト整形ソリューションには、それぞれ長所と（現時点での）短所がありますが、どちらを、いつ使うべきでしょうか？ 考慮すべき点をいくつか挙げます：

* `luaotfload`のネイティブなノードベース処理は、特に大きなCJK OpenTypeフォントではメモリを大量に消費することがあります。CJKテキストの整形にHarfBuzzを使うと、速度の向上とメモリ使用量の削減が期待できます。
* 複雑なスクリプトにはHarfBuzzを使ってください。なぜなら「…インド系文字とアラビア文字のレンダリングを大幅に改善し、そのようなスクリプトに強く推奨されます。」からです（ `luaotfload` マニュアルを参照）。
* へのHarfBuzz統合は `luaotfload` まだ比較的新しく、さらなる開発が進められています。執筆時点（2021年7月）では、luaotfloadの組み込み整形（を設定して `mode=node`）をメイン文書フォントに使うことをお勧めします。特に文書がラテン文字を使う場合です。こちらの [GitHubのissue](https://github.com/latex3/luaotfload/issues/175#issue-801120377)をご覧ください。問題点と議論が要約されています。試してみたい場合は、 `luaotfload` を使ってフォントファイルを読み込み、2つのLaTeXフォントを作成できます。1つはHarfBuzzベースの整形を使い、もう1つはLuaベースの整形を使います。Overleafは [サンプルプロジェクト](#sample-project-arabic-shaping)を作成し、これを示しています。
* 数学用フォントの処理にHarfBuzzを使わないでください。tex.stackexchangeの開発者たちが議論しているように、HarfBuzzは [数学組版用のフォントを扱うようには設計されていません](https://tex.stackexchange.com/questions/544881/does-luahbtex-with-harfbuzz-renderer-completely-supports-math-formating) ので、その目的には使わないでください。

**サンプルプロジェクト：アラビア語の整形**

ここでは、いくつかの高品質なアラビア書体を使って比較するOverleafプロジェクトを紹介します `luaotfload`のノードベースのテキスト整形サービス（`mode=node`）とHarfBuzzのもの（`mode=harf`):

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

このプロジェクトには次の画像に示す出力が含まれています：

![アラビア語の組版](/files/833ba975d3dd20ec59a9376a02eb51c8d7cd1c7b)

### fontspecで「Renderer」を選ぶ

その [ドキュメント](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), `fontspec` 「…XeTeXまたはLuaTeXのいずれかのユーザーがLaTeX文書でOpenTypeフォントを読み込めるようにします」。LuaTeXまたはLuaHBTeXエンジンを使う場合、 `fontspec` LuaLaTeXが `luaotfload` ライブラリをあなたのために読み込み、さらに `luaotfload`の低レベル機能に直接触れる必要を和らげる便利なユーザーレベルコマンド群も提供します。

では、HarfBuzzの整形と、によって提供される組み込み整形のどちらをどう選ぶのでしょうか？ 答えは、優れた `luaotfload`にあります。 [`fontspec` ドキュメント](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf)、特に第VI部：LuaTeX専用フォント機能です。 `fontspec` はという設定を提供します `Renderer` 。これはフォントを次を通じて定義するときに設定できます `fontspec`. `Renderer` フォントの低レベル処理を制御します。注目すべき2つのオプションは

* `Renderer = Node`：OpenTypeフォントを組版するためのデフォルトの「mode」です。これは `luaotfload`のテキスト整形関数を純粋にLuaで実装したものを使用します。
* `Renderer = Harfbuzz`：この「mode」は、HarfBuzzテキスト整形エンジンで使うためにフォントを定義／読み込みします。 `luaotfload` はLuaHBTeXのAPIを使ってHarfBuzzの関数を呼び出します。

詳細は [`fontspec` ドキュメント](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf).

## TeXエンジン、HarfBuzz、そしてカラー絵文字

XeTeXとLuaHBTeXはいずれもHarfBuzzを統合していますが、HarfBuzzのより高度な機能のいくつか、特にOpenTypeカラー・フォントの読み込みと使用に関しては、提供するサポートのレベルが異なります。

### XeTeXとOpenTypeカラー・フォント

述べたように、フォントのグリフを保存するために使われるデータ形式に基づいて、OpenTypeカラー・フォントにはベクターベースとラスターベースの2種類があります。

#### XeTeXとラスターベースのOpenTypeカラー・フォント

XeTeX は、Google のようなラスターベースの OpenType カラー フォントを読み込めません— [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/) TeX Live 2020 に同梱されているものです。たとえば、Noto Color Emoji (NotoColorEmoji.ttf) を読み込もうとすると、XeLaTeX は「Noto Color Emoji が見つかりません」という、誤解を招く可能性のあるエラーで失敗します。XeLaTeX で組版された次の LaTeX コードは、 *動作しません*:

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

[この XeLaTeX コードを Overleaf で開いてください（ ***終了しません*** 動作します）。](https://www.overleaf.com/docs?engine=xelatex\&snip_name=XeTeX+failure\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BNotoColorEmoji.ttf%7D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0A%5Csmiley%0A%5Cend%7Bdocument%7D)

次のエラーで失敗します:

```
! Package fontspec Error: The font "NotoColorEmoji" cannot be found.
```

同様に、XeTeX で処理した単純な Plain TeX の例も失敗します

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

[この Plain TeX (XeTeX) の例を Overleaf で開いてください（ ***終了しません*** 動作します）。](https://www.overleaf.com/docs?engine=latex_dvipdf\&snip_name\[]=main.tex\&snip\[]=%25%5Ctitle%7Bdummy+title%7D%0A%5Cfont%5Cemojifont%3D%22%5BNotoColorEmoji.ttf%5D%22+at+12pt%0A%5Cemojifont+%5Cchar%221F600%0A%5Cbye\&snip_name\[]=readme\&snip\[]=This+project+uses+a+latexmkrc+file+to+run+xetex+not+xelatex\&snip_name\[]=latexmkrc\&snip\[]=%24latex+%3D+%27xetex%25O+%25S%27%3B+%23+to+use+the+xetex+engine\&main_document=main.tex)

Plain TeX の例では、似ていますが少し異なるエラーメッセージが報告されます:

```
! Font \emojifont=[NotoColorEmoji.ttf] at 12.0pt not loadable: Metric (TFM) fil
e or installed font not found.
l.1 \font\emojifont="[NotoColorEmoji.ttf]" at 12pt

このフォントのサイズ データを読み取れませんでした。
そのため、フォント指定は無視します。
[TFM ファイルは TFtoPL/PLtoTF を使って修正できます。]
別のフォント指定を挿入してみてください。
たとえば、`I\font<same font id>=<substitute font name>'. と入力します。
```

**Plain LuaHBTeX の例**

比較のため、LuaHBTeX でコンパイルした最小限の Plain TeX の例を示します

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

[この Plain TeX (LuaHBTeX) の例を Overleaf で開いてください（正常にコンパイルされます）。](https://www.overleaf.com/docs?engine=latex_dvipdf\&snip_name\[]=main.tex\&snip\[]=%25%5Ctitle%7BPlain+TeX+with+LuaHBTeX%7D%0A%5Cinput+luaotfload.sty%0A%5Cfont%5Cemojifont%3DNotoColorEmoji.ttf%3Amode%3Dharf+at+12pt%0A%5Cemojifont+%5CUchar%221F600%0A%5Cbye\&snip_name\[]=readme\&snip\[]=This+project+uses+a+latexmkrc+file+to+run+luahbtex+not+lualatex\&snip_name\[]=latexmkrc\&snip\[]=%24latex+%3D+%27luahbtex+%25O+%25S%27%3B+%23+to+use+the+luahbtex+engine\&main_document=main.tex)

#### XeTeX 失敗の本当の原因

XeTeX が出すエラーメッセージは、問題の実際の原因を部分的に隠しています。OpenType カラー フォント、特にラスターベースの変種は、 *実際の* XeTeX でサポートされています。実際には、XeTeX (Kpathsea) は *見つける* ことはできますが、XeTeX は Noto Color Emoji フォントを完全に *読み込む* ことができず、そのフォントを組版に使うために必要な内部フォントデータ表を初期化できません。内部的には、XeTeX は *始まる* フォントを読み込む過程で、FreeType の「scalability（拡張可能性）」の定義を用いてそれをテストしますが、そのテストは失敗し、XeTeX は標準的で、やや誤解を招きうる TeX エンジンのエラーメッセージを出します。

**TeX 技術メモ**

NotoColorEmoji.ttf に対する XeTeX の処理は、XeTeX 実行ファイルのデバッグ版をコンパイルすることで調査されました。Eclipse IDE を使って XeTeX の関数 `creatFontFromFile(filename, index, pointsize)`にブレークポイントを置き、その後コードをステップ実行して以降の処理を観察しました。

#### XeTeX とベクターベースの OpenType カラー フォント

XeTeX は *読み込む* ベクターベースの OpenType カラー フォントを扱えますが、その結果得られる PDF にカラー絵文字は出力されません—そもそも XeTeX が PDF を生成できるなら、の話ですが。LuaTeX、LuaHBTeX、pdfTeX とは異なり、XeTeX は *直接* 組版済み文書を PDF 形式で出力しません。代わりに、XeTeX は中間の `.xdv` (e**x**tended **dv**i) というファイル形式を出力し、これは `xdvipdfmx`というユーティリティによって PDF に変換されます。執筆時点では、 `xdvipdfmx` 適切なカラー絵文字グリフのデータを PDF に埋め込むことができないため、せいぜい PDF ではモノクロ絵文字—「フォールバック」結果—が見える程度で、使用したフォントによっては何も表示されないこともあります。

以下は、OpenType カラー フォント [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr)を使う XeLaTeX の例です。TwemojiMozilla.ttf は Microsoft の COLR/CPAL ベクター形式でカラー グリフを保存し、TeX Live 2020 に同梱されています。この例では、XeTeX はフォントを読み込み、 `.xdv` および PDF ファイルを生成できますが、絵文字グリフは組版された PDF には現れません:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}
\newcommand{\smiley}{{\emojifont\char"1F600}}
スマイリーはこちら: \smiley
\end{document}
```

[この XeLaTeX コードを Overleaf で開いてください（動作しません）。](https://www.overleaf.com/docs?engine=xelatex\&snip_name=XeTeX+failure\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BTwemojiMozilla.ttf%7D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0AHere+is+a+smiley%3A+%5Csmiley%0A%5Cend%7Bdocument%7D)

対照的に、上のコードは LuaLaTeX では、 `\emojifont` を `fontspec` 設定 `[Renderer=HarfBuzz]`:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}[Renderer=HarfBuzz]
\newcommand{\smiley}{{\emojifont\char"1F600}}
スマイリーはこちら: \smiley
\end{document}
```

[この LuaLaTeX コードを Overleaf で開いてください（動作します）。](https://www.overleaf.com/docs?engine=lualatex\&snip_name=LuaLaTeX+emoji+example\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BTwemojiMozilla.ttf%7D%5BRenderer%3DHarfBuzz%5D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0AHere+is+a+smiley%3A+%5Csmiley%0A%5Cend%7Bdocument%7D)

### LuaHBTeX と OpenType カラー フォント

統合された HarfBuzz の形状形成エンジンと `luaoftload` ライブラリにより、LuaHBTeX は OpenType カラー フォントの 4 種類すべてをサポートします。LuaLaTeX のユーザーは、絵文字を含むテキストの Unicode ベースの処理を最大限に活用したり、OpenType カラー フォントで文書を非常にカラフルに装飾したりできます。

前述のように、OpenType カラー フォントの 4 つの変種は 2 つのグループに分類できます:

* PNG などのラスター画像形式でグリフを含むもの;
* SVG や Microsoft の COLR/CPAL 機構を使うベクターベース形式のもの。

ベクターベースのグリフ形式には、任意のポイントサイズで鮮明なグリフ画像を生成できるという拡張性の利点があります。

**LuaHBTeX で Microsoft COLR/CPAL カラー フォントを使う**

OpenType カラー絵文字フォントにベクター形式を使いたいなら、フォント [TwemojiMozilla.ttf](https://ctan.org/tex-archive/fonts/twemoji-colr?lang=en)を確認してください。これは Microsoft の COLR/CPAL 形式に基づいています。TwemojiMozilla.ttf は TeX Live に含まれていますが、最新バージョンはその [GitHubリポジトリ](https://github.com/mozilla/twemoji-colr/releases) から入手して Overleaf プロジェクトにアップロードできます。

以下は小さな、 `fontspec`ベースの例で、 `Renderer=Harfbuzz`を使い、大きな（ベクター）アヒルの絵文字を組版します:

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

[この LuaLaTeX の例を開いて、ベクターのアヒルを組版してください。](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+an+emoji+duck\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Ctitle%7BDuck+demo%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D400%7D%5D%7BTwemojiMozilla.ttf%7D%0A%5Cemojifont%5CUchar%221F986%0A%5Cend%7Bdocument%7D)

以下は、上の例で生成された（ベクターの）アヒルです:

![](/files/e550bd0e01a98484bcdc8d1210625fd2ae472538)

#### LuaHBTeXでSVGベースのOpenTypeカラーフォントを使う

この記事の更新時点（2023 年 7 月）では、LuaLaTeX で SVG 形式の OpenType カラー フォントを使う方法についての正式な文書はほとんどありません。 [オンラインの議論で出たコメントのいくつかは](https://github.com/latex3/luaotfload/issues/96) 次を使うことを示唆しています `fontspec`のノードリストでは、 `RawFeature`。以下の疑似コードに示すように。 `*ここに SVG フォント ファイル名を入れてください*` を、LaTeX コードから参照可能な SVG ベースのフォント ファイル名に置き換えてください:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emoji[RawFeature={+svg},SizeFeatures={Size=20}]{ここに SVG フォント ファイル名を入れてください}
\emoji ここに絵文字...
\end{document}
```

もし `fontspec` を省略して `luaotfload` を直接読み込む場合は、次のようにフォントを宣言して指定する必要があるかもしれません—私たちの実験では、これを動作させるには `mode=harf` オプションを省略する必要があることが分かりました:

```latex
\font\emoji=[ここに SVG フォント ファイル名を入れてください]:+svg;
```

**いくつかの注意点**

SVG 形式の OpenType カラー フォントを使いたい読者は、次に注意してください:

* 多数のグリフを含む SVG 形式の OpenType フォントは、 [LuaLaTeX にとって処理コストが高くなりうる](#processing-svg-glyph-data) ため、結果として [Overleaf のタイムアウト](/latex/ja/narejjibsu/038-fixing-and-preventing-compile-timeouts.md).
* を引き起こす可能性があります。 [LuaLaTeX によるこれらのフォントのサポートは](https://github.com/latex3/luaotfload/issues/96#issuecomment-530317399)実験的とみなすことができます: 結果はプロジェクトで使用している TeX Live のリリースに応じて変わる可能性があるため、試行しつつ慎重に進めることをお勧めします。

**SVG グリフ データの処理**

SVG により、デザイナーはフォントのグリフを表す複雑でカラフルなデザインを作成できます—ただし、いくつかの SVG 制限があります [OpenType 仕様に記載されている](https://docs.microsoft.com/en-us/typography/opentype/spec/svg)。しかし、LuaHBTeX を含む TeX エンジンは、SVG ファイルやデータ—たとえば SVG 形式の OpenType カラー フォント内のグリフ形状を記述するために使われる SVG データ—を直接取り込む（使用する）ことはできません。LuaHBTeX はそのグリフを組版し、最終的な PDF 文書を生成するためにそれを使えるので、グリフの SVG データは PDF 形式に変換する必要があります。その SVG から PDF への変換は、 `luaoftload`内部の Lua コードによって処理されます: 各グリフの SVG データはフォント ファイルから抽出され、一時的な `.svg` ファイルに保存され、コマンドライン経由で Inkscape を使って PDF に変換されます。SVG データの抽出と PDF への変換には一定の処理オーバーヘッドがかかるため、文書のコンパイル時間が長くなる可能性があります—特に、何千もの絵文字グリフを含む大きな SVG フォントを使う文書では顕著です。

#### ラスターベースの OpenType カラー フォント

**LuaHBTeX で Google の CBDT/CBLC OpenType カラー フォント形式を使う**

[Noto Color Emoji](https://fonts.google.com/noto/specimen/Noto+Color+Emoji) は TeX Live に含まれている OpenType カラー フォントで、Overleaf プロジェクトで簡単に使えます。Noto Color Emoji は絵文字グリフを表すのに PNG 形式の画像を使うため、以下の例に示すように、大きな（ラスター）アヒルの絵文字を組版できます。なお、 `fontspec` フォント宣言（`\emojifont`）は `Renderer=Harfbuzz`.

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

[この LuaLaTeX の例を開いて、ラスターのアヒルを組版してください。](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+a+large+raster+duck\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Ctitle%7BDuck+demo%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D400%7D%5D%7BNotoColorEmoji.ttf%7D%0A%5Cemojifont%5CUchar%221F986%0A%5Cend%7Bdocument%7D)

以下は、上の例で生成されたラスターのアヒルです:

![LaTeX で組版されたラスターのアヒルの絵文字](/files/e936fd0188dc0e17b9f385790a019a0d27fa06fa)

もし `NotoColorEmoji.ttf` を使おうとして `[Renderer=Harfbuzz]` の `fontspec` 宣言を省略すると、LuaHBTeX は失敗し、PDF ファイルを書き出そうとしたときにエラーメッセージを出します:

```latex
! error:  (file /usr/local/texlive/2020/texmf-dist/fonts/truetype/google/noto-em
oji/NotoColorEmoji.ttf) (ttf): loca table not found
```

このエラーが [loca テーブル](https://docs.microsoft.com/en-us/typography/opentype/spec/loca) は [で発生する理由は GitHub で説明されています](https://github.com/latex3/luaotfload/issues/98#issuecomment-531610153).

**LuaHBTeX で Apple の sbix OpenType カラー フォント形式を使う**

オフラインのテストでは、LuaHBTeX が OpenType カラー フォントの `sbix` 変種をサポートしていることが示されていますが、この記事の執筆時点では、アヒルを組版して実演するのに適切なライセンスの `sbix`変種の絵文字フォントを見つけることができていません。どうか [お問い合わせください](https://www.overleaf.com/contact) ご存じでしたらお知らせください。そうすれば、すぐにこの記事を更新してそれを使うようにします。

## LuaHBTeX HarfBuzz API の紹介

![Db.gif](/files/0f51de0932b822f0383b85614ddabca3fd19d8bd) ![Db.gif](/files/0f51de0932b822f0383b85614ddabca3fd19d8bd)

テキスト整形は、特に複雑文字体系の言語や絵文字に対しては本質的に難しい作業なので、当然ながら HarfBuzz は、テキスト整形の操作に慣れていないと扱いが難しい高度なライブラリです。この記事の最後の節では、LuaHBTeX における HarfBuzz の統合と、Lua コード内からそれにアクセスする方法を見ていきます `\directlua`.

私たちの例は、LuaHBTeX HarfBuzz API を示すためにかなり基本的なコードを使っています。少し作為的で、実運用向けの品質でもなく、実用的でもありません。というのも、その目的は核となるいくつかの考え方を紹介することだけだからです。Lua コードは 2 つの `\directlua` チャンクに分けてあり、最初のチャンクでは `luaharfbuzz` ライブラリを読み込み、次の `\directlua` チャンク内で使ういくつかのグローバル変数を作成します。そのチャンクでは、 `\codestoemoji`.

を定義しています。Knuth が使った二重の危険な曲がり角の記号を再現するのがふさわしいと感じます（画像提供: [このサイト](http://www.truetex.com/db.htm)）—なぜなら、内容はやや低レベルで、いわば「内部をのぞく」ものだからです—もっとも、冒険心のある読者には興味深いかもしれません。LuaHBTeX の HarfBuzz 統合は [GitHub 上の luaharfbuzz プロジェクト](https://github.com/ufyTeX/luaharfbuzz/wiki#projects-using-luaharfbuzz) に由来しており、そこには [プロジェクトの紹介](https://github.com/ufyTeX/luaharfbuzz/wiki) と [luaharfbuzz API の一覧](http://ufytex.github.io/luaharfbuzz/).

### 最初の手順: luaharfbuzz ライブラリを読み込み、フォントを見つける

LuaHBTeX の HarfBuzz API を使うには、まず `luaharfbuzz`という、LuaHBTeX に組み込まれているライブラリ（モジュール）を読み込み、その返り値のテーブルを、ここでは `hblib`:

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

次に、適切な絵文字 OpenType カラー フォントを見つける必要があります。ここでは Noto Color Emoji を使います—見つからない場合のエラーチェックはしていない、かなり怠惰な実装であることに注意してください。これを見つけるには、 `kpse` (Kpathsea) ライブラリを使います。これは LuaTeX/LuaHBTeX の一部でもあります:

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

変数 `hblib`を通じて HarfBuzz ライブラリにアクセスでき、適切なフォントへのパス（`pathtofontfile`）が得られたので、 `hblib`を使い始めることができます。まず、マクロを定義する 2 つ目のコード チャンクで使う HarfBuzz フォントと HarfBuzz フェイスを作成します。 `\directlua` 。

```latex
% Noto Color Emoji から HarfBuzz face と HarfBuzz font を作成
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)
```

#### HarfBuzz font と HarfBuzz face: それらは何か?

ある [HarfBuzz face オブジェクト](https://harfbuzz.github.io/fonts-and-faces.html) はフォント ファイルから読み込まれた書体を表しますが、特定のパラメータ（サイズなど）は設定されていません。 [HarfBuzz font オブジェクト](https://harfbuzz.github.io/fonts-and-faces.html) は *特定のインスタンス* の HarfBuzz face を表します。したがって、1 つの HarfBuzz face から複数の HarfBuzz font オブジェクトを派生させることができます。各 HarfBuzz font には、サイズなどのプロパティを異なる値で設定できます。HarfBuzz face は HarfBuzz font よりも高い抽象度にあります。

### フォント グリフを使って PNG ファイルを作成する

最初の `\directlua` チャンクの最後の部分は、 `writePNGglyph(hbfontobject, glyphID)` という関数です。これは、Noto Color Emoji のような一部の OpenType カラー フォントが、含まれる絵文字グリフを表すのに PNG グラフィックを使っていることを示すために使います。

この関数は LuaHBTeX の HarfBuzz API を使ってグリフから PNG データを抽出し、そのデータを `.png` という名前のファイル `Graphics<glyphID>.png`という名前の `.png` ファイルに書き出します。その `\includegraphics` ファイル名は

によって、組版済み PDF に PNG グリフ画像を埋め込むために使うよう返されます。 `writePNGglyph(hbfontobject, glyphID)` が配置されると、最初の `\directlua` コード チャンクは次のようになります:

```latex
\directlua{

% LuaHBTeX から luaharfbuzz ライブラリを読み込む
hblib=require("luaharfbuzz")

% Overleaf のサーバー上で Noto Color Emoji フォントを見つける
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Noto Color Emoji から HarfBuzz face と HarfBuzz font を作成
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% この関数はフォントとグリフ ID を受け取ります:
% グリフの PNG データを抽出し
% .png ファイルに書き出します

function writePNGglyph(hbfontobject, glyphID)

    % グリフの PNG データを取得
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % .png ファイル用のファイル名を構築
    local fname="Glyph"..glyphID..".png"

    % .png ファイルを書き出し、ファイル名を返す
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % \includegraphics が使うファイル名を返す
    return fname
end
}
```

### 2 つ目の \directlua チャンク: マクロ \codestoemoji を作成する

目的は、HarfBuzz に整形させたい絵文字の文字コードを含むテキスト片で呼び出せるマクロを定義することです。具体的には、各絵文字文字を表すのに `\codestoemoji` を使います。たとえば: `\Uchar<文字コード>` \codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}

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

\codestoemoji の定義の中では多くのことが起きています。以下で説明しますが、定義は次のようになっています: `\codestoemoji` \newcommand{\codestoemoji}\[1]{%

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

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

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

if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % グリフのテーブル hbglyphs は 1 始まりです
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % インポートした PNG 画像のサイズを縮小
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}
```

#### マクロ \codestoemoji の定義を理解する

この `\codestoemoji` マクロは、主として Lua コードを `\directlua`の中に含んだものです。ですから、 *どのように* `\directlua` の仕組みについてもっと知りたいなら、Overleaf の記事 [Understanding `\directlua`](/latex/ja/xiang-xi-ji-shi/09-an-introduction-to-luatex-part-2-understanding-directlua.md)を確認してください。そこでは、LuaTeX と LuaHBTeX が `\directlua` をどのように処理するか、特に `\noexpand` や `\unexpanded`.

**\directlua 内のマクロ パラメータ「#1」の扱い**

マクロは次の 3 行から始まります:

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

これらは次の作業を行います:

* `local str="#1"`: これはマクロから渡された入力から Lua 文字列を作成します;
* `local hbbuffer = hblib.Buffer.new()`: これは HarfBuzz API を使って、HarfBuzz に整形させたいテキストを保持するバッファを作成します;
* `hbbuffer:add_utf8(str)`: これは、マクロ入力から作成された UTF-8 形式の文字列を HarfBuzz バッファに追加します。

最初のコード行は

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

かなり単純そうに見えますが、その動作にはかなりの複雑さがあり、少し詳しく見てみる価値があります。

3 行目のコード

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

を見ると、 `str` 変数を使って、HarfBuzz バッファに UTF-8 で形式化された Unicode 文字列を与えていることが分かります。これを機能させるには、変数 `str` 自体が UTF-8 で形式化された Unicode テキストを含んでいなければなりません。そこで疑問が生じます: *どのように* LuaHBTeX は、マクロ引数 `"#1"`に含まれる `\Uchar` コマンドを、HarfBuzz 用の UTF-8 テキストを含む Lua 文字列変数 `str` に「変換」したのでしょうか?

マクロの意図した使い方を見ると `\codestoemoji` マクロ:

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

入力、たとえば `\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065...`は、UTF-8 でエンコードされた絵文字の並びのようには見えません。さらに、HarfBuzz は TeX コマンドについて何も知りません。どういうわけか、 `\Uchar` コマンドからなる生の TeX 入力が、HarfBuzz が使える UTF-8 エンコードの Unicode 文字へ変換されますが、 *どのように*?

答えは `\Uchar` コマンドの振る舞いにあります: `\codestoemoji` が `\char` の代わりに `\Uchar` を呼び出そうとすると失敗しますが、 *なぜでしょうか*?

**\Uchar: \directlua における展開**

その `\codestoemoji` マクロが呼び出されると、マクロ定義の中に格納された `\directlua` コマンドは、LuaHBTeX に組み込まれた Lua インタプリタに送る Lua コードを準備しなければなりません。そのコード準備の一部として、マクロ定義内の元の Lua コードに含まれる TeX/LaTeX コマンドと、ユーザーが与えたマクロ引数の両方を展開します。その展開プロセスはトークン列を生成し、その後それがテキストに戻され、Lua インタプリタに渡すための Lua コードが生成されます。便宜上、Overleaf の記事 [Understanding `\directlua`](/latex/ja/xiang-xi-ji-shi/09-an-introduction-to-luatex-part-2-understanding-directlua.md):

![\directlua の仕組み](/files/4745f09e73b054a42ea5e4e3c2295905754f0b90)

マクロ `\codestoemoji` は `\Uchar` コマンドを使って呼び出されることを意図しており、 [記事の前半で述べたように](#the-key-difference-expansion), `\Uchar` は展開可能なコマンドであり、その展開は文字トークンを生成します。 `\directlua`の処理活動の中で、LuaHBTeX は各 `\Uchar<文字コード>` コマンドを展開する際に *取り除き* 各 `\Uchar<文字コード>` 入力から *置き換え* それを対応する展開値、つまり `<文字コード>`.

を表す文字トークンに置き換えます。 `\directlua` 処理の最終段階では、 *によって生成された最初のトークン列が* テキストに戻されて `\Uchar` テキストに戻されます *: その文字トークンからテキストへの変換によって、元の*値の UTF-8 表現が生成されます。 `<文字コード>` が生まれます。

私たちの例では、Lua コードが生成されて Lua インタプリタに渡せる段階になるころには、「#1」のマクロ入力は UTF-8 テキスト列に変換されています。 `str` 変数は、HarfBuzz バッファに安全に追加できる UTF-8 テキスト文字列になっています。

**なぜ \char は動かないのか?**

率直に言うと、理由は `\char` は *実際の* 展開可能なコマンド。〜とは異なり `\Uchar` コマンド, `\char` コマンド *は取り除かれません* 入力から `\directlua`の初期処理でトークン一覧を生成する際に、これらは「通過」し、 `\directlua`によって構築中のトークン一覧に組み込まれます。たとえば、 `\codestoemoji` に含まれていた `\\char\"1F3F4` LuaHBTeX はそれをトークン列に変換し、生成中のトークン一覧の一部として保存します。

次の処理段階、つまりトークンをテキストに戻す際に、得られる Lua コードには *リテラル文字列* `\\char\"1F3F4` が、変数を定義するために使ったテキストの中に含まれます `str`。 `str` の内容が HarfBuzz バッファに追加されると、絵文字文字「1F3F4」を表す UTF-8 エンコードされたシーケンスは含まれず、代わりにリテラル文字列 `\\char\"1F3F4`、HarfBuzz が整形しようとしますが、私たちの目的では絵文字グリフは生成されません。ちなみに、文字列 `\\char\"1F3F4` も、"ロングブラケット文字列"として作成されない限り Lua の構文エラーを発生させます— [Lua のエスケープシーケンスとは](/latex/ja/xiang-xi-ji-shi/09-an-introduction-to-luatex-part-2-understanding-directlua.md#what-are-e2809clua-escape-sequencese2809d3f) を、この問題の背景として参照してください。

もし `\codestoemoji` に置き換え `\char` コマンドを使おうとすると、次のように:

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

LuaHBTeX は失敗し、次のような構文エラーを報告します:

```latex
[\\directlua]:1: '"\\c' の近くに無効なエスケープシーケンスがあります。
\\codestoemoji ...ing \\includegraphics }.}]]) end }

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

Lua インタプリタで問題が発生したため、
この Lua チャンクの残りは無視されます。
```

#### HarfBuzz の整形関数を呼び出す

**バッファパラメータの設定**

HarfBuzz は、整形を依頼されたテキストについて追加情報を必要とすることがあります。その情報は、 `<buffer variable>` が *のバッファメソッド*を設定することで与えられます。例えば:

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

たとえば、絵文字テキストの方向が左から右であることを HarfBuzz に伝える必要があります。そのために、 `set_direction()` メソッドを `<buffer variable>` （ `hbbuffer`と呼ばれる）に対して次のように使います:

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

ここで `hblib.Direction.new("ltr")` は、Lua 経由で HarfBuzz エンジンに渡すのに適した「方向オブジェクト」を作成します。

**整形を実行する**

バッファが適切に初期化されたら、関数 `shape_full()`を通じて HarfBuzz に実際の整形を依頼できます。例では次のように書きます:

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

の第3および第4パラメータは `shape_full()` 関数の引数は Lua テーブルである必要があります。両方のパラメータには空のテーブル「`{}`」を使っています。 `shape_full()` の一般形は次のとおりです:

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

* **`{"shaper"}`**: 通常は設定する必要はありませんが、オプションは `{"ot"}` または `{"graphite2"}`です。「shaper」の概念についての詳細は [HarfBuzz のドキュメント](https://harfbuzz.github.io/shaping-and-shape-plans.html)を参照してください—これは Lua ベースの（実装）ではなく、低レベルの C API を文書化している点に注意してください。 `luaharfbuzz` バインディング（実装）
* **`{font features}`**: これは、HarfBuzz に整形時に適用させたい [OpenType機能](https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist)—フォントがサポートする—機能を列挙したテーブルです。

使用したいフォント機能は、 `luaharfbuzz` ライブラリ関数

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

ここで

* `library_instance` はあなたの `luaharfbuzz` ライブラリインスタンス変数（`hblib` はこの例）です。
* `feature_string` は [機能を定義するための構文](https://github.com/ufytex/luaharfbuzz/wiki/Feature-Strings)を使います。例として `+smcp` はスモールキャップスを有効にするため、 `-kern` はカーニングを無効にするために使います。

例:

```latex
local dosmcp = hblib.Feature.new("+smcp")
local nokern = hblib.Feature.new("-kern")
% フォント機能はこのように使います
local res = hblib.shape_full(hbfont, hbbuffer, {dosmcp,nokern},{})
```

#### 結果へのアクセス: グリフの取得

そして最後に、整形操作が成功すると、整形済みのグリフはバッファ変数 `hbbuffer` に、コード内で先に作成したものとして返されます。

グリフにはバッファメソッド `get_glyphs()` を通じてアクセスし、ループを使って各グリフを取得します。グリフを保持する Lua テーブル、 `hbglyphs` は、この例では 0 ではなく 1 から始まるインデックスが付けられていることに注意してください。

各グリフの *グリフ識別子* （紛らわしいことに `codepoint`と呼ばれる）と、HarfBuzz フォント（`hbfont`）が `writePNGglyph()` 関数に渡され、このグリフのフォントのラスター画像表現を使って PNG ファイルを作成します。

`writePNGglyph()` は PNG ファイルを書き出し、PNG ファイル名を返します。その名前を使って、（スケールされた）PNG ファイルを `\\includegraphics[scale=0.75]{<fname>}`を介して LaTeX 文書に取り込みます。Lua コード内で `\includegraphics` を直接使える点に注目してください。

```latex
if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % グリフのテーブル hbglyphs は 1 始まりです
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % インポートした PNG 画像のサイズを縮小
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
```

### Overleaf で開ける完全なコード

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

% LuaHBTeX から luaharfbuzz ライブラリを読み込む
hblib=require("luaharfbuzz")

% Overleaf のサーバー上で Noto Color Emoji フォントを見つける
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% Noto Color Emoji から HarfBuzz face と HarfBuzz font を作成
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% この関数はフォントとグリフ ID を受け取ります:
% グリフの PNG データを抽出し、
% .png ファイルに書き出します

function writePNGglyph(hbfontobject, glyphID)

    % グリフの PNG データを取得
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % .png ファイル用のファイル名を構築
    local fname="Glyph"..glyphID..".png"

    % .png ファイルを書き出し、ファイル名を返す
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % \includegraphics が使うファイル名を返す
    return fname
end
}

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

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

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

if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % グリフ表 hbglyphs は 1 から始まるインデックスです。
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % インポートした PNG 画像のサイズを縮小
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}

アヒル: \\codestoemoji{\\Uchar"1F986}

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

[この luaharfbuzz API の例を Overleaf で開く。](/latex/ja/xiang-xi-ji-shi/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md)

この例では次の出力が生成されます:

![Harfbuzzexample.png](/files/390bf08cb229b60e3c4c1e795eeb872a76151e5d)

## ボーナスセクション: 絵文字数式で遊ぶ

最後にちょっと和やかな話題として、Overleaf チームのメンバーが [`絵文字` LaTeXパッケージ](https://ctan.org/pkg/emoji?lang=en) を使って楽しい例を作成しました:

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

[この楽しい例を Overleaf で開く](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Fun+with+emoji+math\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bemoji%7D%0A%5Cusepackage%7Bunicode-math%2Cfontspec%7D%0A%5Csetmainfont%7BSTIX%7D%0A%5Csetmathfont%7BSTIX+Two+Math%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewcommand%7B%5Cemomath%7D%5B1%5D%7B%5Ctext%7B%5Cemoji%7B%231%7D%7D%7D%0A%5C%5B%0Ae%5E%7B%5Cemomath%7Bdroplet%7D+%5Cln%5Cemomath%7Bsmile%7D%7D%3D%5Cemomath%7Bsweat-smile%7D%0A%5C%5D%0A%5C%5B%0Ae%5E%7B%5Cemomath%7Beye%7D%5Cemomath%7Bpie%7D%7D%3D-1%0A%5C%5D%0A%5Cend%7Bdocument%7D)

この例では次の出力が生成されます:

![Emojimath2.png](/files/57d78ae3ebb1b59e2031cffc77c7edfaf22a95fc)


---

# 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/ja/xiang-xi-ji-shi/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.
