マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

チョットpdfTeXでTrueTypeフォントしてみる話

チョット調べてみたところ、某マクロツイーターでは2011年に書かれた一連の「TeXのフォントの取扱」に関する解説記事の中で少しだけ「pdfTeXでTrueTypeフォントする話1」に触れられている。

zrbabbler.hatenablog.com

とはいえ、その記事では「dvipdfmxでOpenTypeフォントする話」のおまけのような扱いに留まっている感じもする。そこで、改めて「pdfTeXでTrueTypeフォントする」方法についての完結した記事を書くことにする。ただし単発の記事で完結させるために以下の方針をとる:

  • 動作原理などの詳細については過去の記事の方に全て任せることにして、ここでは手順だけを述べる。
  • 話を単純にするため、「フォントの中の1つのグリフだけを使えるようにする」というケースについて扱う。

pdfTeXで素敵に源真ゴシックする話

題材として「源真ゴシック」を使うことにする。源真ゴシックには2万弱のグリフがあるが、その中で一つだけ使いたいグリフを選ぶとなると、当然コレになるだろう。

f:id:zrbabbler:20190921032125p:plain
源真ゴシックのU+2603(SNOWMAN)

というわけで、このグリフのみを(文字コード0の位置に)含む本質的なTeX欧文フォント(TFM)である「genshinessential-r」を作成することにする2

※もちろん源真ゴシックの☃は「源ノ角ゴシック」の☃そのものであるが、源ノ角ゴシックはCFFグリフのOpenTypeフォントであるため、ここでは使えない。

encファイルをつくる

文字コード0をU+2603にマップする」ようなエンコーディングを表すencファイル「essential.map」を作る。

[essential.map]
/essential-enc [
/u2603
] def

少し補足しておくと、encファイルの書式は以下の通りである。

/エンコーディング名 [
/文字コード0に対するグリフ名
/文字コード1に対するグリフ名
/文字コード2に対するグリフ名
・・・・・・
/文字コード255に対するグリフ名
] def

「グリフ名とは何か」というのは本当はヤヤコシイ話なのであるが、ここで紹介する手順に従う(otftotfmを使う)のであれば、単純に「U+2603のグリフ名はu26033と考えてかまわない。

エンコーディング名」については後の設定と整合する限りは勝手に決めてかまわない。

encファイルの仕様としては必ず文字コード0~255に対するグリフ名を書く必要があり、今回のように「0しか使わない」という場合でも、残りの255個の位置に“未定義”を表す.notdefというグリフ名を並べる必要がある。でもどうやらotftotfmでは後ろの.notdefは省略しても通用する4ようなので、ここでは横着をした。

TFMをつくる

このessential.encとフォントファイルGenShinGothic-Regular.ttfを入力として、otftotfmを用いてTFMを作成する5

※入力ファイルはカレントディレクトリに置いておく。

otftotfm -e essential.enc GenShinGothic-Regular.ttf genshinessential-r >genshinessential.map

ここで標準出力をリダイレクトしていることに注意。otftotfmはpdfTeX用のマップ行を標準出力に出すので、これをgenshinessential.mapに保存しておく。このコマンドの実行により、以下のファイルが生成される。

  • genshinessential-r.tfm: TFMファイル。
  • a_fdlbd4.enc6: 元のessential.encを“加工”して作られたencファイル。実際にpdfTeXで使うのはこちらの方である。(essential.encはもはや不要。)
  • genshinessetial.map: pdfTeX用のマップファイル。

otftotfmは“間にVFを挟んだTFM”を生成する7ことが多いのであるが、今回は非常に単純な事例であったため単純に.tfmファイル一つだけからなるTFMになったようだ。

早速pdfTeXでgenshinessentialしてみる

これで“TeXレベル”でgenshinessential-rを利用するための準備は全て整った。そこでまずはplain pdfTeXの文書で動作をテストしてみる8

[test-plain.tex]
% plain pdfTeX document
% マップファイル読込の指定
\pdfmapfile{+genshinessential.map}
% TFM"genshinessential-r"からフォント \fEsssential を生成
\font\fEssential=genshinessential-r
% フォントを \fEssential に切り替えてコード0のグリフを出力
Test: {\fEssential\char0}
\bye

plain pdfTeXなのでpdftexコンパイルする。

pdftex test-plain

端末出力をみると、今の作業で作ったファイルや源真ゴシックのフォントファイルがちゃんと読み込まれていることが確認できる。

(./test-plain.tex{c:/texlive/2019/texmf-var/fonts/map/pdftex/updmap/pdftex.map}
{genshinessential.map} [1] ){a_fdlbd4.enc}<c:/texlive/texmf-local/fonts/truetyp
e/public/GenShinGothic/GenShinGothic-Regular.ttf><c:/texlive/2019/texmf-dist/fo
nts/type1/public/amsfonts/cm/cmr10.pfb>
Output written on test-plain.pdf (1 page, 14867 bytes).

そして出力されたtest-plain.pdfの中身を確認すると……。

f:id:zrbabbler:20190921044841p:plain
plain pdfTeXな出力結果

素敵☃!

今度はpdfLaTeXでgenshinessentialしてみる

無事にplain TeXで源真ゴシックできたので次はLaTeXでのサポートについて考えることにしよう。

LaTeXのサポートというと「当該のフォント(ファミリ)に切り替える命令」を提供するのが普通であるが、今の事例ではそれは意味を成さないだおる。今作ったTFMは「文字コード0しかない」という特殊なものであり、それでできることは「源真ゴシックの☃を出す」ことだけなので、そのための専用の命令を用意するべきだろう。そこで、LaTeXパッケージ「genshinessential」の設計について、次のような方針にする。

  • 「源真ゴシックのU+2603〈☃〉を出力する」ための命令\genshinsnowmanを提供する。
  • U+2603のグリフにはシェープ(ウェイトなど)による差異が元々存在しない。だから、単一のシェープのみを定義して、\genshinsnowmanは常にそれを使うことにする。
  • マップファイルをパッケージファイルと別に用意する必然性は乏しいので、パッケージ中でマップ行を宣言することにする。

現状のマップ行自動生成の名前が入っていて少し汚らしいので整理しよう。まずは、a_fdlbd4.encの先頭の部分(%00の行より前)を次のように書き換えたものを新たにessential.encとして保存する。(つまり、a_fdlbd4.encの代わりにessential.enc、AutoEnc_fdl・・・2raの代わりにessential-encを使うようにする。)

/essential-enc [
%00
  /uni2603 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
  /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
・・・・・・

パッケージファイルgenshinessential.styの実装は次のようにした。

※マップ行でessential.encや/essential-encを使っていることに注意。

[genshinessential.sty]
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{genshinessential}

% マップ行読込の指定.
\pdfmapline{+genshinessential-r GenShinGothic-Regular "essential-enc ReEncodeFont" <[essential.enc <GenShinGothic-Regular.ttf}

% ファミリ'genshinessential'の定義.
% エンコーディングは'U'(不定形)を指定する.
\DeclareFontFamily{U}{genshinessential}{}
% m/nシェープしか使わないのでそれだけを定義する.
\DeclareFontShape{U}{genshinessential}{m}{n}{<->genshinessential-r}{}

%<*> \genshinsnowman: "源真ゴシック"のU+2603を出力する.
\newcommand{\genshinsnowman}{{\usefont{U}{genshinessential}{m}{n}\symbol{0}}}

これでLaTeXのサポートが完成したことになる。改めて整理すると:

  • genshinessential-r.tfm: TFMファイル。
  • essential.enc: (判りやすい名前の)encファイル。
  • genshinessetial.sty: LaTeXパッケージファイル。

早速genshinessetialパッケージを使ってみよう。

[test-latex.tex]
% pdfLaTeX document
\documentclass[a4paper]{article}
% 素敵なパッケージを読み込もう
\usepackage{genshinessential}
\begin{document}
% 素敵な命令を使おう
Hello \genshinsnowman\ world!
\end{document}

もちろん今度はpdflatexでコンパイルする。出力結果は……。

f:id:zrbabbler:20190921051700p:plain
pdfLaTeXな出力結果

トッテモ素敵☃!

まとめ

源真ゴシックの☃は素敵!


  1. 当該の記事ではTrueTypeフォントだけに限らず一般のOpenTypeフォント(TrueTypeグリフもCFFグリフも含めて)が対象になっている。実際、pdfTeXで両種のOpenTypeフォントが扱えるのであるが、CFFグリフのOpenTypeについては「サブセット埋込ができない」という重大な制限がある。このため、実用的に使えるのは専らTrueTypeフォントに限られることになるだろう。

  2. 「genshinessential-r」の名前は例によって“ZR命名規則”に依る。エンコーディング不定形(1つしかグリフがない)なので省略し、バリアント部を「r」(Regular)、ファミリ部を「genshinessentia」とした。

  3. Unicode値は「4桁以上の大文字16進数で書く」という規則なので、例えばU+0038ならu0038、U+1F92Eならu1F92Eがグリフ名となる。uni2603というグリフ名も可能だが、この方式は5桁以上では使えない。

  4. 最初に手動で作るencファイルはotftotfmの入力となった後は一切使われない。

  5. TrueTypeフォントが与えられた場合、Type1への変換は非対応であるため--no-type1--no-dotlessjは事実上常に有効になる。今の目的に照らすとOpenTypeフィーチャ(-f ligaなど)を指定する必要もないだろう。

  6. 生成されたencファイルの名前(およびその中に記されたエンコーディング名)は自動生成されるので、環境によって異なる可能性がある。

  7. VFが使用された場合、「genshinessential-r.tfm」の他に「genshinessential-r.vf」と「genshinessential-r–base.tfm」が生成されるはずである。つまり、「genshinessential-r」は「genshinessential-r–base」を参照するVFである。

  8. pdfTeXの普通のマップ設定に割り込むのは面倒なので、代わりに「文書内で(\pdfmap...プリミティブで)マップ設定を行う」という方法をとる。詳細については[過去の記事]の方を参照。