matplotlib でフォントを埋め込む方法

matplotlib とかその派生の seaborn で作った図(PDF)を論文に貼りたいが、その図にフォントが埋め込まれないときの対処メモ。焦らず、まずは心を落ち着けよう。

症状

PDF ファイルのフォントの埋め込み状況を確認すると Type3 フォントが埋め込まれてない。フォント名としては DejaVuSans とか。ヤバイ、カメラレディの提出に間に合わない。

対処方法1

matplotlib で図を生成するとき、Type3 フォントではなくTrueType フォントを使うように指定する。

具体的には、図を描画する前に以下の命令を実行する。

matplotlib.rc('pdf', fonttype=42)

これでフォントが埋め込まれた。以下で確認できる。

$ pdffonts demo.pdf 
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
DejaVuSans                           CID TrueType      Identity-H       yes no  yes     24  0
DejaVuSans-Bold                      CID TrueType      Identity-H       yes no  yes     15  0

何をやっているか?

使用した matplotlib.rc 関数の API は以下にある。

matplotlib.org

PDF の設定についてはこのあたりに書かれている。

### PDF backend params
#pdf.compression:    6  # integer from 0 to 9
                        # 0 disables compression (good for debugging)
#pdf.fonttype:       3  # Output Type 3 (Type3) or Type 42 (TrueType)
#pdf.use14corefonts: False
#pdf.inheritcolor:   False

デフォルトが Type3 フォントで、42 にすると TrueType フォントが使われるということらしい。なぜか TrueType にするとフォントが埋め込まれる。ラッキー。

対処方法2

上記の方法はサブセット埋め込み(sub)になっていないのでファイルサイズが大きい。

そんなときは以下のように pgf バックエンドで描画するとよい(ただし実行には LaTeX 環境の構築が必要)。

plt.savefig("demo.pdf", backend="pgf")

フォント名が変わったけど必要な文字だけサブセット埋め込みになっているのでいい感じ。

$ pdffonts demo.pdf 
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
EJSLOC+DejaVuSans                    CID TrueType      Identity-H       yes yes yes      7  0

何をやっているか?

PDF の描画を pgf というバックエンドにより行っている。LaTeX の処理系を使っている。詳細は以下にある。

matplotlib.org

おしまい。

■ 参考