Rでのフォントの扱い

RでPDFを生成する際にフォントの扱いが問題になる。特に最近はすべてのフォントを埋め込む(embedする)よう指示されるので,それに対応する方法をまとめておく。

PDFにフォントが埋め込まれているかどうか調べるには,Adobe Readerで開いてファイル→プロパティ→フォントで調べるか,あるいはXpdfの pdffonts コマンドで調べる。

以下はMac(El Capitan)および一部Windows 10,CentOS 7上のR 3.2.3でテストした。

pdf() による方法

関数 pdf() を使う方法である。フォントについては R News の Volume 6/2 pp.41-46 に詳しい。

pdf("pdf-ex.pdf", family="Japan1GothicBBB", width=7, height=4)
par(mgp=c(2,0.8,0))
curve(dnorm(x), xlim=c(-3,3), main="正規分布")
dev.off()
pdf() example

これで GothicBBB-Medium という和文フォントが名前参照で使われるが,フォントは埋め込まれない。フォントを埋め込むには別途 embedFonts() という関数を使う。これはGhostscriptを呼び出してフォントを埋め込む。システムにGhostscriptがインストールされていなければならない。実際の挙動はGhostscriptの設定に依存する。

embedFonts("pdf-ex.pdf", outfile="pdf-ex-embed.pdf")

cairo_pdf() による方法

cairo_pdf("cairo-ex.pdf", family="Japan1GothicBBB", width=7, height=4)
par(mgp=c(2,0.8,0))
curve(dnorm(x), xlim=c(-3,3), main="正規分布")
dev.off()
cairo_pdf() example

MacでCairoを使うにはX11が必要である。私のMacでは MS-Gothic (埋め込みサブセット) となった[MS Gothicが入ってないマシンでどうなるか要確認]。Linux(CentOS 7)では CairoFont-1-1 (埋め込みサブセット) VL-Gothic-Regular (埋め込みサブセット) となった。Windows 10では Arial-BoldMT (埋め込みサブセット) CairoFont-0-0 (埋め込みサブセット) で日本語部分が表示されなかった。

quartz() による方法

MacのPDFレンダリングエンジンを使う方法である。Macでしか使えないが,Macの任意のシステムフォントが埋め込める。

quartz(type="pdf", file="quartz-ex.pdf", width=7, height=4)
par(family="HiraKakuProN-W3")
par(mgp=c(2,0.8,0))
curve(dnorm(x), xlim=c(-3,3), main="正規分布")
dev.off()
quartz() example

family=... で指定するフォント名は,/Library/Fonts や /System/Library/Fonts にあるフォントファイル名から拡張子を外したものを基本として,別名も用意されている。以下はEl Capitanで使える和文用のヒラギノフォントである。

par(family="ヒラギノ明朝 ProN W3")    # 3,6
par(family="Hiragino Mincho ProN W3") # 同上
par(family="HiraMinProN-W3")          # 同上

par(family="ヒラギノ角ゴシック W3")   # 0-9
par(family="Hiragino Sans W3")        # 同上
par(family="HiraginoSans-W3")         # 同上

par(family="ヒラギノ丸ゴ ProN W4")    # 4だけ
par(family="Hiragino Maru Gothic ProN W4") # 同上
par(family="HiraMaruProN-W4")         # 同上

par(family="ヒラギノ角ゴ ProN W3")    # 3,6(旧)
par(family="Hiragino Kaku Gothic ProN W3") # 同上
par(family="HiraKakuProN-W3")         # 同上

部分ごとにフォントを変えることもできる。例えば軸にHelvetica,タイトルにヒラギノを使うのであれば,次のようにする。

curve(dnorm(x), xlim=c(-3,3), family="Helvetica")
title(main="正規分布", family="HiraKakuProN-W6")

実はQuartzのフォントは別の方法でも設定できる。

quartzFonts()
$serif
[1] "Times-Roman"      "Times-Bold"       "Times-Italic"     "Times-BoldItalic"

$sans
[1] "Helvetica"             "Helvetica-Bold"        "Helvetica-Oblique"    
[4] "Helvetica-BoldOblique"

$mono
[1] "Courier"             "Courier-Bold"        "Courier-Oblique"    
[4] "Courier-BoldOblique"

という定義済みのリストがあるので,これを変更する。例えば

quartzFonts(sans=quartzFont(c("Helvetica","HiraKakuProN-W3","HiraKakuProN-W6","HiraMaruProN-W4")))

もう一度 quartzFonts() と打って,変わったことを確認する。

こうして quartzFonts() で登録された各ファミリの4個のフォントのうち何番目をどこに使うかはデフォルトでは次のように定められている:

par(font.axis=1, font.lab=1, font.main=2, font.sub=1)

これも自由に変更できる。変更したら par() と打ち込んで確認できる。

このことを使った例:

quartzFonts(sans=quartzFont(c("Helvetica","HiraKakuProN-W3","HiraKakuProN-W6","HiraMaruProN-W4")))
quartz(type="pdf", file="quartz-ex2.pdf", width=7, height=4)
par(family="sans")
par(font.axis=1, font.lab=2, font.main=3, font.sub=4)
par(mgp=c(2,0.8,0))
curve(dnorm(x), xlim=c(-3,3), xlab="横軸 x", ylab="縦軸 dnorm(x)", main="正規分布")
dev.off()
quartz() example

軸の文字,ラベルの文字,メインタイトルの文字が自動的に違うフォント(Helvetica,ヒラギノ角ゴ ProN W3,W6)に割り振られたことが確認できる。

showfont

showtext パッケージを使えば任意のシステムフォントが使える。ただし文字情報はなくなり,アウトライン化される。使い方は Using system fonts in R graphs やGitHubの yixuan/showtext を見る。

install.packages("showtext")
library(showtext)
font.add("marugo", "ヒラギノ丸ゴ ProN W4.ttc")
pdf("showfont-ex.pdf", width=7, height=4)
par(mgp=c(2,0.8,0))
showtext.begin()
curve(dnorm(x), xlim=c(-3,3), main="正規分布", family="marugo")
showtext.end()
dev.off()
showfont example

Windowsでもやってみた。

font.add("meiryo", "meiryo.ttc")
pdf("showfont-ex.pdf", width=7, height=4)
par(mgp=c(2,0.8,0))
showtext.begin()
curve(dnorm(x), xlim=c(-3,3), main="正規分布", family="meiryo")
showtext.end()
dev.off()
showfont example

ちゃんとメイリオのグリフが使われている(文字情報はない)。

extrafont

extrafont パッケージ。使い方はGitHubの wch/extrafont に簡潔に書かれている。TrueTypeしか使えない。私の環境ではうまく使えなかったので省略する。