fontspec(Xe / Lua)

同じ三行のプリアンブルが、LuaLaTeX では通り、XeLaTeX では ! Package fontspec Error: The font "TeX Gyre Termes" cannot be found. で止まる——これは環境が壊れているのではなく、fontspec の設計そのものです。fontspec は LaTeX でフォントを 書体名で 呼ぶためのパッケージで、\setmainfont の一行だけで本文書体が替わります。ただし「その名前で探す相手」がエンジンによって違い、そこが実際に文書を壊す唯一の場所です。このページは、名前解決の食い違いを中心に据えて、\setmainfont\newfontfamily・ファイル指定・OpenType 機能キーまでを実測つきで通します。

fontspec が動くエンジン — pdfLaTeX で使えない理由

fontspec が動くのは XeLaTeX と LuaLaTeX の二つだけ で、pdfLaTeX では \usepackage{fontspec} の時点でエラーになります。理由は歴史的なものです。1980 年代の TeX は、TFM という自前のメトリック形式と Type 1 / METAFONT のフォントしか知りません。OpenType も、システムのフォントデータベースも、TeX が作られたあとに世界のほうが用意したものです。XeTeX と LuaTeX はその世界に合わせて外側から作り直されたエンジンで、Unicode の入力と OpenType のフォントをネイティブに扱えます。fontspec はその新しい能力を LaTeX の語彙に翻訳する層であって、pdfTeX には翻訳すべき能力そのものがありません。

読み込みは \usepackage{fontspec} の一行だけです。XeLaTeX・LuaLaTeX 向けのクラスやパッケージ(bxjsarticleunicode-mathluatexja-fontspec など)は内部で先に読み込んでいることが多く、あとから明示的に書いても二重読み込みにはなりません。pdfLaTeX の文書を移してくるときは、\usepackage[T1]{fontenc}\usepackage[utf8]{inputenc} を外すのを忘れないでください。前者は fontspecTU エンコーディングに置き換えるので不要、後者は Unicode エンジンでは意味がありません。

\setmainfont / \setsansfont / \setmonofont で本文書体を替える

文書の三本柱は \setmainfont{…}(ローマン体=本文の既定書体)、\setsansfont{…}\textsf\sffamily が選ぶ書体)、\setmonofont{…}\texttt\ttfamily の等幅書体)で決まります。引数は書体名かフォントファイル名。fontspec はそこから太字・斜体・太斜体の四つ組を自動で探し当て、\textbf\textit\emph に割り当てるので、本文の書きかたは何も変わりません。この「四つ組を自動で揃える」働きが fontspec の中心的な仕事で、あとで見るように、それが崩れたときにだけ設定を書き足すことになります。

document.tex
% compile with lualatex (or xelatex — see the next section)
\documentclass{article}
\usepackage{fontspec}
\setmainfont{TeX Gyre Termes}   % roman / body
\setsansfont{TeX Gyre Heros}    % sans serif
\setmonofont{TeX Gyre Cursor}   % monospaced
\begin{document}
Body text, \textbf{bold}, \textit{italic}, \textsf{sans}, \texttt{mono}.
\end{document}

これらは プリアンブルに書く のが原則です。理由は一つ、LaTeX が数式用のフォントを固めるのが \begin{document} の時点だから。プリアンブルで \setmainfont を実行すれば、\mathrm など数式中のローマン体にも同じ書体が回りますが、本文中に書いた場合は本文だけが替わり、数式のローマン体は取り残されます。数式そのものの書体は fontspec の管轄外で、unicode-math\setmathfont が担当します——本文と数式でコマンドが分かれていることを覚えておいてください。

The font "…" cannot be found. — XeLaTeX と LuaLaTeX でフォントの探し方が違う

! Package fontspec Error: The font "…" cannot be found.XeLaTeX でだけ 出るなら、それは名前の綴り間違いではなく、探す相手の違いです。XeTeX は OS のフォントデータベースに問い合わせます。 OS に「インストールされている」書体しか見えません。LuaTeX は luaotfload が自前で索引を作り、そこに TeX ツリーの中も含めます。 TeX Live が同梱するフォントは OS には登録されていないので、この差がそのまま結果の差になります。手元の TeX Live 2024 で確かめた例では、同一のファイルが LuaLaTeX では通り、XeLaTeX では止まりました。

terminal
$ xelatex t1.tex
! Package fontspec Error: The font "TeX Gyre Termes" cannot be found.

$ lualatex t1.tex
Output written on t1.pdf (1 page, 3697 bytes).

$ pdffonts t1.pdf
name                            type          encoding    emb sub uni
NNOCLB+TeXGyreTermes-Regular    CID Type 0C   Identity-H  yes yes yes

この境目は「同梱フォントか、OS のフォントか」で引かれます。実測すると、Hiragino Mincho ProNHiragino SansYuMincho のように OS 側にインストールされた書体は XeLaTeX でもそのまま解決します。逆に、TeX Live が texmf-dist/fonts/opentype/public/ 以下に配る書体——TeX Live 2024 ではこのディレクトリに 125 個のパッケージ(実ファイルは .otf が 1,499 本)が入っています——は、XeLaTeX からは名前で見えません。エンジンそのものの設計思想は /learn/engines/xetex/learn/engines/luatex が扱います。ここで必要なのは、壊れた文書を今すぐ直す手順 です。

直しかたは二つです。(1)lualatex でコンパイルする。 一行も書き換えずに済むので、ほとんどの場合これが最短です。(2)書体名ではなくファイル名を書く。 \setmainfont{texgyretermes-regular.otf} は XeLaTeX でも通ります。ただし代償があり、ファイル名で呼ぶと fontspec は太字・斜体を推測できません。実際に \textbf を使うと LaTeX Font Warning: Font shape 'TU/texgyretermes-regular.otf(0)/b/n' undefined が出て、太字のつもりの箇所が細いまま出力されます。ここが「エラーにならないので気づきにくい」典型例です。ファイル名は大文字小文字も区別されます——TeXGyreTermes-Regular.otf と書くと、同じ書体なのに cannot be found に戻ります。

ファイルで指定する — Path= / Extension= / BoldFont=

ファイル指定の完全形は、四つのスタイルを一つずつ手で割り当てる書きかたです。Path= でディレクトリ、Extension= で拡張子(.otf.ttf)を与え、UprightFont=BoldFont=ItalicFont=BoldItalicFont= に各ファイルを対応させます。値の中のアスタリスク * は、第一引数に書いた 共通の基底名に置き換わる プレースホルダです。前節で消えた太字・斜体は、この四つを書けば戻ってきます——実測でも、四つを与えた版は Font shape … undefined の警告がゼロになり、pdffonts に Regular・Bold・Italic・BoldItalic の四つが並びました。

document.tex
\usepackage{fontspec}
% XeLaTeX-safe: name the files, and name all four styles
\setmainfont{texgyretermes}[
  Extension      = .otf ,
  UprightFont    = *-regular ,
  BoldFont       = *-bold ,
  ItalicFont     = *-italic ,
  BoldItalicFont = *-bolditalic ,
]

% fonts shipped inside the project directory
\setsansfont{LibreBaskerville}[
  Path        = ./fonts/ ,
  Extension   = .otf ,
  UprightFont = *-Regular ,
  BoldFont    = *-Bold ,
]

どちらの書きかたを選ぶかは、その文書を誰が組むか で決めるのが実務的です。自分の環境で読むだけの下書きなら書体名が速い。共著・投稿・CI・Docker のように 他人か他機のマシンでも同じ PDF が出てほしいなら、Path= でプロジェクト内にフォントを同梱する 方式がほぼ唯一の確実な手です。fontspecPath= を与えられたとき、TeX の検索パスではなくその相対パスを直接見にいくので、リポジトリごと持ち運べます。

指定方法書き方向いている場面XeLaTeX で同梱フォントを引けるか
By name\setmainfont{TeX Gyre Termes}下書き・私用文書。太字と斜体が自動で揃ういいえ。OS 登録済みの書体だけ
By file, upright only\setmainfont{texgyretermes-regular.otf}とりあえず通したいとき。太字は出ないはい。ただし \textbf が細いまま
By file, all fourPath / Extension / UprightFont / BoldFont / ItalicFont / BoldItalicFont共同執筆・投稿・CI・自作フォント。再現性が最優先のときはい。Font shape … undefined の警告も出ません

\newfontfamily で四番目・五番目の書体を足す

ローマン・サンセリフ・等幅の三枠に収まらない書体は、\newfontfamily で自分の切り替え命令を作って足します。第一引数が作りたい命令名、第二引数が書体名で、\setmainfont と同じオプションをそのまま取れます。作られた命令は \rmfamily と同じ 宣言型 なので、そこから先すべてに効きます。効かせる範囲は {\titlefont …} と波括弧で囲んで区切ってください。

document.tex
\usepackage{fontspec}
\newfontfamily\titlefont{TeX Gyre Bonum}
\newfontfamily\quotefont{TeX Gyre Schola}[Scale = MatchLowercase]
% ...
\titlefont A heading in Bonum

{\quotefont A quoted passage in Schola.}

一度きりの書体なら、定義せずに \fontspec{書体名} をその場で宣言として使えます。ただし \fontspec は呼ばれるたびにフォントを読み込み直すので、章見出しのように何度も出てくる書体をこれで書くと、コンパイル時間だけがじわじわ伸びます。二回以上使うなら \newfontfamily が定石です。なお \newfontfamily は同名の命令が既にあると失敗します——\sc\it のような LaTeX に元からある短い名前は避け、\titlefont のように用途の分かる名前を付けてください。

OpenType の機能をキーで呼ぶ — Ligatures / Numbers / Scale

OpenType フォントの中には、合字・数字の異体・スモールキャップスといった代替字形が最初から入っており、fontspecキー=値のオプション でそれを引き出します。効果は目で見るより測るほうが早いので、TeX Gyre Pagella の 10pt で実測した値を添えます。たとえば Numbers=OldStyle を掛けると 0123456789 の深さが 0.19998pt から 2.37999pt に増えます——旧式数字が 39 にディセンダを持つことが、数値にそのまま出ています。

  • Ligatures= — 合字と入力変換。Ligatures=TeX--→ en ダッシュ、---→ em ダッシュ、`''→ 曲がった引用符という **TeX 流の書きかた** を有効にします(実測:--- が 9.99pt の「ハイフン三つ」から 10.0pt ちょうど= 1 em の em ダッシュに変わります)。ほかに Common(fi・fl などの標準合字)、NoCommon(それを切る。実測で fi の幅が 6.05pt → 6.35pt)、RareDiscretionaryHistoric`。
  • Numbers= — 数字のスタイル。OldStyle(本文になじむ旧式数字)/Lining(高さのそろう近代数字)と、ProportionalMonospaced を組み合わせます。表の中の数字は Lining,Monospaced にすると桁が縦にそろいます。
  • Letters=SmallCaps — 本物のスモールキャップス。Libertinus Serif で実測すると Abc の高さが 6.98pt → 6.58pt、幅が 16.26pt → 16.94pt になります。注意:フォントが smcp を持たない場合、fontspec は警告も出さずに何もしません(TeX Gyre Pagella では幅が 17.6pt のまま動きません)。Letters=Uppercase などの値もあります。
  • SmallCapsFeatures= — スモールキャップスのときだけ効かせたい機能をまとめて渡します(例:SmallCapsFeatures={Numbers=OldStyle})。同じ要領で UprightFeatures=BoldFeatures=ItalicFeatures= があり、スタイルごとに設定を変えられます。
  • Scale= — 拡大率。数値のほか Scale=MatchLowercase(小文字の高さを本文にそろえる)と Scale=MatchUppercase(大文字の高さをそろえる)。実測では TeX Gyre Heros の x-height 5.24pt が、Pagella 本文に合わせて 4.68999pt = Pagella の 4.69pt にぴたりと一致しました。
  • StylisticSet= — フォントが用意する代替字形セットを番号で選びます。RawFeature= はキーが用意されていない機能を OpenType のタグで直接渡す抜け道で、RawFeature={+onum}Numbers=OldStyle と同じ結果になります(実測で深さも同じ 2.37999pt)。
  • Script= / Language= — 文字体系と言語を指定します(Script=ArabicLanguage=Turkish など)。Renderer= はどの整形エンジンを使うかの指定で、XeTeX では AATOpenTypeGraphite を選べます。LuaTeX では luaotfload が処理するため、このキーは基本的に不要です。
document.tex
\usepackage{fontspec}
\setmainfont{TeX Gyre Pagella}[
  Ligatures = TeX ,
  Numbers   = OldStyle ,
  SmallCapsFeatures = {Numbers = Lining} ,
]
% match the sans to the body x-height
\setsansfont{TeX Gyre Heros}[Scale = MatchLowercase]

文書全体ではなく一箇所だけ機能を足したいときは \addfontfeature{…}(複数なら \addfontfeatures{…})を使います。いま有効な書体に指定の機能を 局所的に上書きする 命令で、囲んだ波括弧の中だけに効きます。旧式数字で本文を組んでいる文書の、表の中の数字だけを揃えたい——という場面がまさにこれです。

latex
Set in old-style figures, but this column
{\addfontfeature{Numbers={Lining,Monospaced}} 01234 56789}
lines up digit by digit.

fontspec が担当しないもの — 数式と和文

fontspec が受け持つのは 本文の欧文書体だけ で、数式と和文には別の系統があります。数式は unicode-math を読み込んで \setmathfont{…} に OpenType 数式フォント(Latin Modern Math、STIX Two Math、NewCM Math など)を渡します。\setmainfont を替えても数式は一切動かないので、本文と数式で顔がちぐはぐになるのは pdfLaTeX に限った話ではありません。どの数式フォントを選ぶかは数式書体のページの領分です。

和文も同じ構図です。\setmainfont は欧文書体だけを替え、漢字・かなには何も起こりません。LuaLaTeX では fontspec の和文版というべき luatexja-fontspec を読み込み、\setmainjfont{…}(明朝=和文の本文)・\setsansjfont{…}(ゴシック)・\newjfontfamily という「j 付き」の命令を使います。オプションの書きかたは fontspec とほぼ共通なので、Scale=Path= の知識はそのまま持ち込めます。つまり欧文と和文で 二系統を並走させる のが Unicode エンジンでの日本語組版の形です。どの和文フォントを選べるかは和文フォントのページで扱います。