Help us understand the problem. What is going on with this article?

LuaTeXでカラーフォント・絵文字✌(SVG/COLR/CBDT)

TeX & LaTeX Advent Calendar 2019 1日目の記事です。2日目はt-kemmochi氏の「xfakebold.styの紹介」です。今年も「TeX & LaTeX Advent Calendar」が始まりました。今年の重点テーマは「やっぱりLua(La)TeXしよう」です。Lua(La)TeXに関する情報がたくさん集まりそうです。この記事は

Screenshot at 2019-11-14 21-59-47.png

のようなカラーフォントをLuaLaTeX(およびその親戚)で使おうという記事です。カラーフォントの応用の一つに絵文字がありますが、LuaTeXに限らずTeX一般で絵文字を少ない手間で使うにはbxcoloremoji.styもおすすめです。

luaotfload 3.1以降

以下の作業の多くで2019年11月にリリースされたluaotfloadのバージョン3.1以降が必要になります。最新のluaotfloadとluatexをインストールする代表的な方法としてはTeXLiveW32TeXがあります。Debian Linuxならtexlive-luatexパッケージの2019.20191112-1またはそれ以降のバージョンにも含まれるのでapt-get -t testing install texlive-luatexでインストールすることもできます。以下ではluaotfloadの\fontコマンドを使いますが

\font\新フォントコマンド={[フォントファイル名]:フォントオプション1;フォントオプション2;...;}

という形式で使います。フォントの名前でもフォント指定できますが詳しくはluaotfloadの説明書をご覧下さい。またfontspec.styの\fontspecコマンドは

\fontspec{フォント指定}[RawFeature={\fontに与えるのと同じフォントオプション}]

のように使います。\fontspecに与えるフォント指定とオプションの順番は逆にしてもよいです。詳しくはfontspecの説明書をご覧ください。

OTF(OpenType Font)カラーフォントの形式

詳しい説明はカラー絵文字〜OpenTypeフォントの仕様を中心に〜にあるため、ここでは簡単に紹介します。まず第一にOTFカラーフォントは正式なOTF規格ですが、PDF規格ではOTFカラーフォントに対応しておらず、現在使われているPDFビューワーもOTFカラーフォントを理解できないため、OTFカラーフォントをTeXが扱うためにはカラー字形を頑張ってPDF等に変換する必要があり、開発者が大変です。また字形が画像として埋め込まれることが多いためコピー&ペーストできるようにするためにTeXが頑張る必要があります。そこらへんの苦労はBringing world scripts to LuaTeX: The HarfBuzz experiment, TUGBoat, vol.40, no.1, pp.38-43に詳しく書かれています。またPicture Fonts: welcome to a (beautiful) messにはConTeXtにおけるカラー絵文字の扱いが書いてあります。LuaTeXのカラーフォントの扱いは基本的にはConTeXtと同じになります(しかしTeXLive 2020からはConTeXtとHarfBuzzが並立する模様)。

SVG in OpenType形式

欧文フォント

ベクターグラフィックスのよく用いられる形式であるSVG(Scalable Vector Graphics)がそのままフォントファイルに入っている形式です。カラー字形の表現力はこの形式が最も高く、グラデーションを含む字形はこの形式だけで表現できます。またAdobeが推しているため絵文字以外に非常にたくさんのカラーフォントがこの形式で提供されています。SVGはそのままPDFに書けないため、AdobeはType 3 PostScriptフォント形式に変換して埋め込み、ConTeXt/LuaTeXはinkscapeを用いてPDFに各字形を変換してそのPDFを埋め込みます。

カラー字形の変換にinkscapeを用いるのでまずinkscape -A file.pdf file.svgで適当なSVGファイルfile.svgをfile.pdfに変換できるようにする必要があります。上記の準備ができたら、ColorTubeフォントPlayboxフォントをダウンロードしてカレントディレクトリにおいて、下記のファイルをlualatex --shell-escapeでコンパイルすると記事冒頭のPDFファイルができます。--shell-escape+svgを付加するのがポイントです。

\documentclass{minimal}
\usepackage{bxtexlogo}
\bxtexlogoimport{LuaLaTeX}
\usepackage{fontspec}

\begin{document}
\fontspec{Playbox-FREE.otf}[SizeFeatures={Size=16},RawFeature={+svg;+kern;+liga;}]
\noindent
Color Font in \LuaLaTeX

\bigskip
\noindent
\fontspec{ColorTube.otf}[RawFeature={+svg;+kern;}]
Color Font in \LuaLaTeX
\end{document}

luaotfload 3.1あたりではtexmf-dist/tex/luatex/luaotfload/fontloader-2019-10-29.lua:27743: attempt to call a nil value (field 'getindices').というエラーが出ます。この対応策はfontloader-2019-10-29.lua の中の関数otfsvg.topdfからgetindicesを呼び出す部分を削除することです。この問題はluaotfloadのgithubに連絡済みです(luaotfload 3.12で修正されたので上記のファイルは問題なくPDFに変換される)。無料のカラーフォントを配布しているページをいくつか以下に挙げます。

和文フォント

SVGカラー字形を持つ初めての和文フォントとしてSource Han Code JP/源ノ角ゴシック Code JP がありますが、以下のファイルを

\documentclass[b5paper,12pt]{ltjsarticle}

% 以下の2行はカラー字形を構成するコードポイントをJAchar扱いとする
\ltjdefcharrange{33}{"2615,"263A,"263B,"2764,"FE0F,"1F4A9,"1F512,"1F916}
\ltjsetparameter{jacharrange={+33}}

\begin{document}
\jfont\myjfont={name:Source Han Code JP:+svg;+ccmp;jfm=ujis;} at 12pt\myjfont
Source Han Code JP--源ノ角ゴシック Codeは\\
7つのカラーグリフ☕☺️☻❤️💩🔒🤖を含みます。
\end{document}

lualatex --shell-escapeでコンパイルすると以下のPDFを得て、カラーフォントはluatexjaでもバッチリ扱えます。

Screenshot at 2019-11-16 03-53-57.png

SVGカラー字形をさらに踏み込んで活用した商用和文フォントとして「貂明朝」があります。

COLR/CPALカラーフォント形式

複数の字形と対応する色があり、それらを重ね書きしてカラー字形を表現する形式です。もともとMicrosoftが推していた形式でWindows付属のSegoe UI Emojiがこの形式です。無料で使えるフォントとしてはTwemoji Mozillaがあります。TwemojiMozilla.ttfをカレントディレクトリにおいて

\documentclass{minimal}
\begin{document}
\font\twemoji={[./TwemojiMozilla.ttf]:+colr;+ccmp;+dist;}
\font\segoe={name:Segoe UI Emoji:+colr;+ccmp;+dist;}
\noindent
\twemoji ⛄👨‍👩‍👧‍👦💔\\
\segoe ⛄👨‍👩‍👧‍👦💔
\end{document}

(TeXLive 2019の最終版にTwemoji Mozillaが入ったので、TeXLiveやW32TeXの最新版を使っている場合上記の[./TwemojiMozilla.ttf]の代わりにname:Twemoji Mozillaと書いても大丈夫です)をlualatexでコンパイルすると
Screenshot at 2019-11-10 17-03-42.png
というPDFができます。💔の片方が黒くなるバグが発生した場合luaotfloadを新しくすると直ります(バージョン3.1では問題なかった)。

+colrを付けるのがポイントで、fontspec.styを使うときはRawFeature={+colr}とします。Twemojiが妙に詰まっているのはフォント自体のバグ(こことかここ)である疑いがあります。

CBDT/CBLCカラーフォント形式

グーグルが推す形式でPNG画像がそのままフォントファイルに入っています。 https://github.com/googlefonts/noto-emoji/tree/master/fonts から NotoColorEmoji.ttf をダウンロードしてカレントディレクトリに置いてください。ConTeXtがCBDT/CBLC形式を扱えないため、ConTeXtの代わりにHarfBuzzを用いて組版できるlualatex-devluaotfload 3.1以降を用いる必要があります。TeXLiveならびにW32TeXの最新版はlualatex-devとluaotfloadの最新版を含みます。

$ lualatex-dev emoji6.tex
This is LuaHBTeX, Version 1.11.2 (TeX Live 2020/dev) 

のようにLuaHBTeXと表示されることを確認してください。lualatex-devとluaotfloadの新しい版を使えるようにした上で

\documentclass{minimal}
\begin{document}
\font\twemoji={[./TwemojiMozilla.ttf]:mode=harf;+ccmp;+dist;}
\font\segoe={name:Segoe UI Emoji:mode=harf;+ccmp;+dist;}
\font\noto={[./NotoColorEmoji.ttf]:mode=harf;+ccmp;+dist;}
\noindent
\twemoji ⛄👨‍👩‍👧‍👦💔\\
\segoe ⛄👨‍👩‍👧‍👦💔\\
\noto ⛄👨‍👩‍👧‍👦💔
\end{document}

(TeXLive 2019の最終版にNoto Color Emojiが入ったので、TeXLiveやW32TeXの最新版を使っている場合上記の[./NotoColorEmoji.ttf]の代わりにname:Noto Color Emojiと書いても大丈夫です)をlualatex-devでコンパイルすると

Screenshot at 2019-11-10 17-24-40.png

というPDFを得ます。mode=harfを付けるのがポイントで、fontspec.styを用いるときはRenderer=HarfBuzzを付けてください。

LuaTeX-jaで絵文字を用いるときの注意点

LuaTeX-jaはunicodeコードポイントを和文(JAchar)と欧文(ALchar)に分けて扱っています。またunicode絵文字は複数のコードポイントから構成されることがあります。絵文字を構成するコードポイントは基本的にALcharですが一部JAcharになっていることがあります。文章中の絵文字の中のコードポイントが一部JAcharになっているとうまく絵文字が出ません。例えば

\documentclass[b5paper,12pt]{ltjsarticle}
\usepackage{luatexja-fontspec}
%\input emojialchar.tex

\begin{document}
\fontspec[Renderer=HarfBuzz]{NotoColorEmoji.ttf}\noindent
ふえぇ❣️😳💦あと1ヶ月ちょっとでクリスマス🎄🎅なのに彼女💏💑💕がいないって
やば❕❓😱💦⤵️このままだと令和最初‼のクリスマス🎄✨は😦クリ
ぼっち😢💔😖⤵️ぴええん😭💔実は🙊💭フォロワーさんの中に🌝✨好きな
人😘👦💕がいるんだけどDMで告白💐💌💖してくれたら
オケ🙆‍♂️✨するのになぁ❤😘
\end{document}

lualatex-devでコンパイルすると
Screenshot at 2019-11-12 07-37-51.png

のように一部の絵文字が豆腐になります。対処法としては絵文字の中に現れるコードポイントを全部ALchar扱いにするお呪い(詳しくはLuaTeX-jaの説明書の4.1節を熟読)を使うと期待通りにPDFを生成します。絵文字に現れるすべてのコードポイントをALchar扱いにするファイルをemojialchar.texに置いてあります。emojialchar.tex\inputなどで読むと先程の豆腐が消えて以下のようなPDFを正しく得られます。

Screenshot at 2019-11-12 07-36-49.png

最初は「🙆‍♀️ ♂」だったのが「🙆‍♂️」の表示が変わっているところが若干興味深いです。これは♂がJAcharなので「🙆‍♂️」がALcharの「🙆‍♀️」とJAcharの「♂」に分解されていることに起因します。一つの絵文字の中にJAcharとALcharが混在すると一つの絵文字が複数の文字に分割されて組まれることはおそらく仕様です。またfontspecの代わりにluaotfloadの\fontコマンドを使うと実行時エラーが起きますが、すでに修正されています。

複数のフォントの組み合わせ

あるフォントに無い字形(例えば絵文字)を他のフォントから取ってくる方法は、
- 欧文フォントについてはluaotfload説明書の7節に、
- 和文フォントについてはLuaTeX-jaの説明書の9.4節、10.2節、11.1節に(zr_tex8r氏による使用例
書いてあります。欧文フォントの合成の例は以下のような感じになります

\documentclass{minimal}

\font\colorfont={[./ColorTube.otf]:+svg;+kern;} at 10pt
\font\twemoji={[./TwemojiMozilla.ttf]:+colr;+ccmp;+dist;} at 14pt
\font\combo={combo: 1->\fontid \colorfont ; 2->\fontid \twemoji ,fallback}
\begin{document}
\combo
Font Combination in \TeX❣✌
\end{document}

Screenshot at 2019-11-16 09-39-29.png

最後に…

過去の「TeX & LaTeX Advent Calendar」で初日がzr_tex8r氏ではなかったことは皆無なので、今後のTeX界での身の振り方を考えたほうがいい気がしてきました…😱

qiita掲載の過去のTeX LaTeX Adventカレンダーの記事一覧はこれ https://qiita.com/search?q=%22LaTeX+Advent%22&sort=stock です。

この記事の手順はTeXファイルとフォントファイルが同一ディレクトリに置かれる前提でしたが、それでは面倒なので頻繁に使うフォントはシステムの標準の場所に置いてlualatexが名前でフォントを見つけられるようにしたほうが便利です。Linuxの場合にそうする手順はLinux上のLuaTeXに手動でフォントをインストールする手順に説明しました。WindowsやMacでも同等なことができますがわからないので、良い説明記事をご存知でしたらコメント等で教えてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした