Ghostscript 9.10 - CJK fonts, Outlined EPS

TeX Live 2013 on Mac OS X Mavericks 環境構築の一環で,Ghostscript 日中韓フォント設定を行った。これまで何度もやっているのにすぐ忘れてしまう。備忘録を残しておく。その際使ったいくつかのシェルスクリプトも掲載しておく。参考になれば幸いである。Ghostscript 対象バージョンは 9.10。MacPorts がいつの間にやら勝手にインストールしていたもの。Ghostscript は,いろんな画像処理ソフトウェアがこれを前提としているので,知らないうちにいくつものバージョンが組込まれていた...。

LaTeX 組版では dvipdfmx を用いて DVI ファイルを PDF 形式に変換して閲覧・印刷するのが,現在の主流ではないかと思う。それでも,PostScript インタープリタ Ghostscript は,LaTeX 出力を画像形式に変換するのに有用である。たとえば,同時に使うことの難しい LaTeX パッケージの文書断片を別のアウトライン EPS(Encapsulated PostScript)に出力しておいて,これを \includegraphics で取り込んで同一文書に仕上げる,といった工夫が可能になる。アウトライン EPS は文字フォントがベクトル画像に変換された形式の EPS で,文字情報のない完全なベクトル画像であって,フォント環境に依存しない可搬性がある。ベクトル画像ゆえに拡大しても画像は滑らかである。そういったメリットがある。もちろん,\includegraphics は PDF も処理できるし,フォント埋め込み PDF なら環境に依存せずきれいな文字で見られるので,アウトライン EPS にこだわる必要はないのだけど...。

思い出した。何年か前に Type1 フォント埋め込みの PDF が版下では問題なかったのにイメージセッタで文字化けする,というトラブルを経験したことがある。このとき Ghostscript を使ってフォントのアウトラインを取った EPS に差し替えて解決したのだった。フォント埋め込み PDF は万能とは限らないと認識した次第。[2014.4.9 追記]

フォントの設置

日本語漢字は Mac OS 添付のヒラギノ OpenType フォント,中国語と韓国語とはそれぞれ ArphicUn-fonts の TrueType フォントを使うようにしよう。Mac OS 付属の 华文宋体.ttf 等の中韓フォントは埋め込みに問題が出るようで,これらを選択しないことにする。

設定すべきフォントは,ファミリ,ウェイトと CMap の組み合わせでいくつもバラエティの広がりがあるわけだが,中韓については TeX Live 2013 標準で添付されている otf-cktx.map(OTF パッケージが出力するフォントメトリックを DVI ware がどのフォントグリフで処理すべきかを記述したマップ)の定義の範囲で行うこととする。

% 韓国語
otf-ukmr-h   UniKS-UCS2-H  HYSMyeongJoStd-Medium
otf-ukmr-v   UniKS-UCS2-V  HYSMyeongJoStd-Medium
otf-ukgr-h  UniKS-UCS2-H HYGoThic-Medium
otf-ukgr-v  UniKS-UCS2-V HYGoThic-Medium
% 中国語簡体字
otf-ucmr-h   UniGB-UCS2-H STSongStd-Light
otf-ucmr-v   UniGB-UCS2-V STSongStd-Light
otf-ucgr-h UniGB-UCS2-H STHeiti-Regular
otf-ucgr-v UniGB-UCS2-V STHeiti-Regular
% 中国語繁体字
otf-utmr-h   UniCNS-UCS2-H MSungStd-Light
otf-utmr-v   UniCNS-UCS2-V MSungStd-Light
otf-utgr-h  UniCNS-UCS2-H MHei-Medium
otf-utgr-v  UniCNS-UCS2-V MHei-Medium
% 後略 — これ以降は使用フォントが同じなので

適当にコメントを入れてある。この定義は,左端の DVI 出力フォントに対し,DVI ware が用いるべき CMap(中央)とフォント名(右端)とを示す。Ghostscript から見れば,dvips 等が出力した PostScript に対し,この後ろの二つの情報に基づいてフォントを扱うことになる。UniCNS-UCS2-H 等の Far East な CMap は,かつては Adobe サイトから取り寄せなければならなかったが,いまや Ghostscript パッケージに組込まれるようになった。

ヒラギノ日本語フォントについては,updmap-sys ProN フォント埋め込み設定がなされている(sudo updmap-sys --setoption kanjiEmbed hiragino を発行することで,ヒラギノ埋め込み設定の一連の関連マップが登録されている)ものとする。

これらのフォントを Ghostscript 管理下のディレクトリにシンボリックリンクとして設置する。ヒラギノ OpenType フォントは拡張子なしでシンボリックリンクを作成する。筆者環境では Arphic,Un-fonts を CJK パッケージのためにすでにインストールしてあるので,TeX ツリーからリンクを貼る。

シェルスクリプト mksymlink.sh を以下に掲げる。これを実行すると,ヒラギノについては /opt/local/share/ghostscript/9.10/Resource/CIDFont/ 下に,中韓フォントについては /opt/local/share/ghostscript/fonts/TrueType/ 下にシンボリックリンクを設置する。Arphic, Un-fonts が手元になければ,リンクからダウンロードして TeX ツリーに格納し,そのパスで書き換えていただきたい。また,Ghostscript のパスも MacPorts によるインストールの場合であって,独自に導入した場合はそれに準じて指定しなければならない。スクリプト中の TFD, GSOTF, GSTTF 変数設定を吟味いただきたい。

#!/bin/sh
# -*- coding: utf-8; mode: shell-script; -*-
# make symbolic link for Ghostscript 9.10 on Mac OS X Mavericks
 
SFD=/System/Library/Fonts
LFD=/Library/Fonts
TFD=/usr/local/texlive/texmf-local/fonts/truetype
GSOTF=/opt/local/share/ghostscript/9.10/Resource/CIDFont
GSTTF=/opt/local/share/ghostscript/fonts/TrueType
 
# japanese hiragino
ln -s $SFD/"ヒラギノ明朝 ProN W3.otf" $GSOTF/HiraMinProN-W3
ls -l $GSOTF/HiraMinProN-W3
ln -s $SFD/"ヒラギノ明朝 ProN W6.otf" $GSOTF/HiraMinProN-W6
ls -l $GSOTF/HiraMinProN-W6
ln -s $SFD/"ヒラギノ角ゴ ProN W3.otf" $GSOTF/HiraKakuProN-W3
ls -l $GSOTF/HiraKakuProN-W3
ln -s $SFD/"ヒラギノ角ゴ ProN W6.otf" $GSOTF/HiraKakuProN-W6
ls -l $GSOTF/HiraKakuProN-W6
ln -s $LFD/"ヒラギノ角ゴ StdN W8.otf" $GSOTF/HiraKakuStdN-W8
ls -l $GSOTF/HiraKakuStdN-W8
ln -s $LFD/"ヒラギノ丸ゴ ProN W4.otf" $GSOTF/HiraMaruProN-W4
ls -l $GSOTF/HiraMaruProN-W4
ln -s $LFD/"ヒラギノ明朝 Pro W3.otf" $GSOTF/HiraMinPro-W3
ls -l $GSOTF/HiraMinPro-W3
ln -s $LFD/"ヒラギノ明朝 Pro W6.otf" $GSOTF/HiraMinPro-W6
ls -l $GSOTF/HiraMinPro-W6
ln -s $LFD/"ヒラギノ角ゴ Pro W3.otf" $GSOTF/HiraKakuPro-W3
ls -l $GSOTF/HiraKakuPro-W3
ln -s $LFD/"ヒラギノ角ゴ Pro W6.otf" $GSOTF/HiraKakuPro-W6
ls -l $GSOTF/HiraKakuPro-W6
ln -s $LFD/"ヒラギノ角ゴ Std W8.otf" $GSOTF/HiraKakuStd-W8
ls -l $GSOTF/HiraKakuStd-W8
ln -s $LFD/"ヒラギノ丸ゴ Pro W4.otf" $GSOTF/HiraMaruPro-W4
 
mkdir -p $GSTTF
 
# Chinese: Arphic http://www.ctan.org/tex-archive/fonts/arphic
# - gbsn00lp.ttf  簡体字 GB  serif
# - gkai00mp.ttf  簡体字 GB  sans-serif
# - bsmi00lp.ttf  繁体字 CNS serif
# - bkai00mp.ttf  繁体字 CNS sans-serif
ln -s $TFD/arphic $GSTTF/arphic
ls -l $GSTTF/arphic/
 
# Korean: Un-fonts http://kldp.net/projects/unfonts/
# - UnBatang.ttf, UnBatangBold.ttf  KS serif
# - UnDotum.ttf, UnDotumBold.ttf    KS sans-serif
ln -s $TFD/un-fonts $GSTTF/un-fonts
ls -l $GSTTF/un-fonts/


PostScript CID フォントリソースの生成と格納

Ghostscript は OpenType 漢字フォントについては,CIDFont ディレクトリにフォントの実体を設置しておくだけでなく,Font ディレクトリ下に PostScript CID フォントリソースを格納しておかなければならない。これは DVI ware が出力したフォント名と CMap とからフォント実体のグリフにアクセスするための情報で,たとえば以下のようなテキストファイルである。

/HiraMinProN-W3-UniJIS-UTF16-H
/UniJIS-UTF16-H /CMap findresource
[/HiraMinProN-W3 /CIDFont findresource]
composefont pop

このようなファイルを,使用するフォントについて,対となる CMap の分,作成しておかなければならない。これらはインターネットを探せば誰かがすでに作成してくれているはずで,それを持って来るのが一番早いかも知れない。でも,シェルスクリプトで回せばさっさと出来てしまう。今回設定のために作成・使用したスクリプト mkgsfntres.sh は次のとおり。

#!/bin/sh
# Generate Ghostscript PostScript font resource
# see: http://ghostscript.com/doc/current/Use.htm#CIDFonts
 
# CIDFont name
JPF="HiraMinProN-W3 HiraMinProN-W6 HiraKakuProN-W3 HiraKakuProN-W6 \
     HiraKakuStdN-W8 HiraMaruProN-W4 \
     HiraMinPro-W3 HiraMinPro-W6 HiraKakuPro-W3 HiraKakuPro-W6 \
     HiraKakuStd-W8 HiraMaruPro-W4"
# CMap
JPM="H V Identity-H Identity-V UniJIS-UCS2-H UniJIS-UCS2-V \
     UniJIS-UTF8-H UniJIS-UTF8-V UniJIS-UTF16-H UniJIS-UTF16-V \
     UniJIS2004-UTF16-H UniJIS2004-UTF16-V"
# gen
for i in $JPF
do
    for j in $JPM
    do
        echo "/$i-$j\n/$j /CMap findresource\n[/$i /CIDFont findresource]\ncomposefont pop" > $i-$j
    done
done

これを実行すると,カレントディレクトリにたくさんのリソースファイルが生成される。これらを /opt/local/share/ghostscript/9.10/Resource/Font 下に移動する。

Ghostscript CID フォントの扱いについては How to use Ghostscript を参照のこと。

cidfmap の編集

PostScript ファイルにあるフォントを実際どの実体フォントで出力するかを対応付ける cidfmap を準備する。ヒラギノ埋め込み設定がされていれば /Ryumin-Light 等の伝統的 PostScript フォント名ではなく,マップファイルに従って /HiraMinProN-W3 の名で PostScript ファイルに格納されているはずである。一応,/Ryumin-Light で来たときに /HiraMinProN-W3 に紐付ける定義も入れておこう。中韓は上記範囲のフォントの定義に限定したものである。

%!
%% format: /Substituted  /Original  ;
%%% Japanese OpenType CID Hiragino
/Ryumin-Light            /HiraMinProN-W3      ;
/Ryumin-Medium           /HiraMinProN-W3      ;
/FutoMinA101-Bold        /HiraMinProN-W6      ;
/MidashiMin-MA31         /HiraMinProN-W6      ;
/GothicBBB-Medium        /HiraKakuProN-W3     ;
/FutoGoB101-Bold         /HiraKakuProN-W6     ;
/MidashiGo-MB31          /HiraKakuStdN-W8     ;
/Jun101-Light            /HiraMaruProN-W4     ;
%%% Simplefied Chinese GB
/STSongStd-Light         /BousungEG-Light-GB  ;
/STHeiti-Regular         /GBZenKai-Medium     ;
%%% Traditional Chinese CNS
/MSungStd-Light          /ShanHeiSun-Light    ;
/MHei-Medium             /ZenKai-Medium       ;
%%% Korean KS
/HYSMyeongJoStd-Medium   /UnBatang            ;
/HYGoThic-Medium         /UnDotum             ;
 
%% TrueType fonts entries
%%% Chinese: Arphic Technology
%%% See http://www.ring.gr.jp/pub/GNU/non-gnu/chinese-fonts-truetype/
%%% Simplefied Chinese
/BousungEG-Light-GB  << /FileType /TrueType /CSI [(GB1) 5]  /Path (./TrueType/arphic/gbsn00lp.ttf) >> ;
/GBZenKai-Medium     << /FileType /TrueType /CSI [(GB1) 5]  /Path (./TrueType/arphic/gkai00mp.ttf) >> ;
%%% Traditional Chinese
/ShanHeiSun-Light    << /FileType /TrueType /CSI [(CNS1) 5] /Path (./TrueType/arphic/bsmi00lp.ttf) >> ;
/ZenKai-Medium       << /FileType /TrueType /CSI [(CNS1) 5] /Path (./TrueType/arphic/bkai00mp.ttf) >> ;
 
%%% Korean: Un-fonts Core
%%% See http://kldp.net/projects/unfonts/
/UnBatang       << /FileType /TrueType /CSI [(Korea1) 2] /Path (./TrueType/un-fonts/UnBatang.ttf)  >> ;
/UnDotum        << /FileType /TrueType /CSI [(Korea1) 2] /Path (./TrueType/un-fonts/UnDotum.ttf)   >> ;

これを /opt/local/share/ghostscript/9.10/Resource/Init/ 下にコピーする。

以上で Ghostscript CJK フォント設定は完了である。

試験

Ghostscript 用に設置した CJK フォント以外にも,数式,キリル文字,複式アクセント付きギリシア文字,ニクダー(母音記号)付きヘブライ文字,教会スラヴ文字,タイ文字,ヴェトナム文字の混在した文書で試験してみる。凝りに凝ったフォントで試験しよう。platex もいまや ε-TeX 拡張が取り込まれ,右から左に書くヘブライ語も問題なくタイプセット出来るようになった。

% -*- coding: utf-8; mode: latex; -*-
% gscjkfont.tex - Ghostscript CJK フォント試験
\documentclass[b5paper]{jsarticle}
\usepackage[utf8x]{inputenc}%
\usepackage[T2A,T1]{fontenc}%
\usepackage[thai,vietnam,polutonikogreek,russian,oldchurchslavonic,
            nippon]{babel}% Babel 多言語
\usepackage[deluxe,expert,multi,jis2004]{otf}% OTF 和文(齋藤氏)
\usepackage{cjhebrew}% ヘブライ語
\usepackage{txfonts}%
\renewcommand{\baselinestretch}{1}%
\DeclareFontFamily{LST}{cmr}{}%
\DeclareFontShape{LST}{cmr}{m}{n}{<-> s * [1.20] fslavrm}{}%
\let\oldnum=\oldstylenums%
\pagestyle{empty}% これがないとノンブルのゴミが入ってしまう
\begin{document}
\begin{minipage}{.85\textwidth}
% Math formula - 美文書作成入門の例より
\large
\[ \left(\int_0^\infty \frac{\sin x}{\sqrt{x}} dx \right)^2 =
\sum_{k=0}^\infty \frac{(2k)!}{2^{2k}(k!)^2} \frac{1}{2k+1} =
\prod_{k=1}^\infty \frac{4k^2}{4k^2 - 1} = \frac{\pi}{2} \]
 
\vspace{1em}
\normalsize
(ヨハネ傳\CID{8583}\CID{13664}書) 太初に言あり、言は\CID{8580}と偕にあり、
言は\CID{8580}なりき。\par
% Chinese Simplified
(\CIDC{4351}\UTFC{7FF0}\UTFC{798F}\UTFC{97F3} \CIDC{2149}\UTFC{4F53}%
\UTFC{4E2D}\UTFC{6587}) \UTFC{592A}\UTFC{521D}\UTFC{6709}%
\UTFC{9053}\penalty10000\UTFC{3001}\UTFC{9053}\UTFC{4E0E}\UTFC{3000}%
\UTFC{795E}\UTFC{540C}\UTFC{5728}\penalty10000\UTFC{3001}\UTFC{9053}%
\UTFC{5C31}\UTFC{662F}\UTFC{3000}\UTFC{795E}\penalty10000\UTFC{3002}\par
% Chinese Traditional
(\UTFT{7D04}\UTFT{7FF0}\UTFT{798F}\UTFT{97F3} \UTFT{7E41}\UTFT{9AD4}%
\UTFT{4E2D}\UTFT{6587}) \UTFT{592A}\UTFT{521D}\UTFT{6709}%
\UTFT{9053}\penalty10000\UTFT{3001}\UTFT{9053}\UTFT{8207}\UTFT{3000}%
\UTFT{795E}\UTFT{540C}\UTFT{5728}\penalty10000\UTFT{3001}\UTFT{9053}%
\UTFT{5C31}\UTFT{662F}\UTFT{3000}\UTFT{795E}\penalty10000\UTFT{3002}\par
% Korean
(\UTFK{C694}\UTFK{D55C}\UTFK{BCF5}\UTFK{C74C}) \UTFK{D0DC}\UTFK{CD08}%
\UTFK{C5D0} \UTFK{B9D0}\UTFK{C500}\UTFK{C774} \UTFK{ACC4}\UTFK{C2DC}%
\UTFK{B2C8}\UTFK{B77C}.\par
% Classical Greek
\selectlanguage{polutonikogreek}
\textlatin{(Greek)} >En >arq~h| >~hn <o l'ogoc, ka`i <o l'ogoc >~hn 
pr`oc t`on Je'on, 
ka`i Je`oc >~hn <o l'ogoc.\par
% Russian
\selectlanguage{russian}
(Russian) \CYRV{} \cyrn\cyra\cyrch\cyra\cyrl\cyre{} 
\cyrb\cyrery\cyrl\cyro{} \CYRS\cyrl\cyro\cyrv\cyro, \cyri{} 
\CYRS\cyrl\cyro\cyrv\cyro{} \cyrb\cyrery\cyrl\cyro{} \cyru{} 
\CYRB\cyro\cyrg\cyra, \cyri{} \CYRS\cyrl\cyro\cyrv\cyro{} 
\cyrb\cyrery\cyrl\cyro{} \CYRB\cyro\cyrg.\par
\selectlanguage{oldchurchslavonic}
% OldSlav Old Church Slavonic 
\textlatin{(ChurchSlavonic)}
\OCSVEDI\OCSert{} \OCSnash\OCSaz\OCScherv\oksija{\OCSaz}\OCSlyude\OCSyat{} 
\OCSbuki\varija{\OCSyat} \OCSslovo\OCSlyude\oksija{\OCSon}\OCSvedi\OCSon, 
\zvatelco{\OCSizhe} \OCSslovo\OCSlyude\oksija{\OCSon}\OCSvedi\OCSon{} 
\OCSbuki\varija{\OCSyat} \OCSkako\OCSert{} \OCSbuki\ttlnrm{\OCSglagol}\OCSuk, 
\zvatelco{\OCSizhe} \OCSbuki\ttlnrm{\OCSglagol}\OCSert{} 
\OCSbuki\varija{\OCSyat} \OCSslovo\OCSlyude\oksija{\OCSon}\OCSvedi\OCSon.\par
% cjhebrew Hebrew
\selectlanguage{nippon}%
(Hebrew \textit{Gen.} \oldnum{1}--\oldnum{1})\par
\begin{cjhebrew}
b*:re'+siyt b*ArA' 'E:lohiym 'et ha+s*Amayim w:'et hA'ArE.s; w:hA'ArE.s 
hAy:tAh tohU wAbohU w:.ho+sEk: `al--p*:ney t:hOm w:rU/a.h 
'E:lohiym m:ra.hEpEt `al--p*:ney ham*Ayim;
\end{cjhebrew}\par
(Thai) %
\selectlanguage{thai}%
\def\wbr{\hskip0pt plus0.6pt minus0.6pt\relax}%タイ語ワードブレーク
\fontencoding{LTH}\fontfamily{norasi}\selectfont%
ศิลปะ{\wbr}ไทย{\wbr}มี{\wbr}ลักษณะ{\wbr}เฉพาะตัว{\wbr}ค่อนข้าง{\wbr}สูง{\wbr} 
โดย{\wbr}มี{\wbr}ความ{\wbr}กลมกลืน{\wbr}และ{\wbr}คล้ายคลึง{\wbr}กับ{\wbr}%
ศิลปวัฒนธรรม{\wbr}เพื่อนบ้าน{\wbr}อยู่{\wbr}บ้าง{\wbr}\par
\selectlanguage{nippon}%
(Vietnamese) %
\selectlanguage{vietnam}%
Phần ``Những câu hỏi và giải đáp thường gặp'' 
được nêu ra ở đây nhằm mục đích thu thập 
những câu hỏi thường gặp trong thực tế và những lời giải 
đáp thích hợp nhất của nó.
\end{minipage}
\end{document}

この原稿を platex で処理し DVI を生成する。これを dvips で中間 EPS(文字情報を含んだ EPS)に変換する。次に中間 EPS を gs epswrite デバイス指定でアウトライン EPS に変換する。ターミナルのオペレーションは次のようなものである。

$ platex gscjkfont.tex
$ dvips -Ppdf -E -D 10000 gscjkfont.dvi -o tmp.eps
$ gs -dNOPAUSE -dBATCH -sDEVICE=epswrite -r10000 -sOutputFile=gscjkfont.eps tmp.eps

gscjkfont.eps を Mac OS プレビューで確認する。OTF パッケージのマクロで出力した日中韓の文字が,設定した CJK フォント(のベクトル画像)できちんと表示されるはずである。dvips が出力した EPS tmp.eps の場合,プレビューは PostScript フォントを処理出来ずエラーを出すが,アウトラインを取ったものなら画像と同じように(EPS を自動的に PDF 変換した上で)表示する。次のように gscjkfont.eps を PDF gscjkfont.pdf に変換し,Adobe Reader で文書のプロパティを確認すると,数式含め文字のフォント情報がなく,すべて画像に変換されていることがわかる。すべて画像なので当然ながら PDF ビュアのテキスト選択ツールは使えなくなっている。ベクトル画像は jpeg, png などのビットマップ画像とは異なり拡大しても粒子の荒さが目立たない。

$ epstopdf --filter < gscjkfont.eps > gscjkfont.pdf
20140407-gs-outline-pdf.png
gscjkfont.pdf
20140407-gs-outline-zoom.png
拡大表示

DVI からアウトライン EPS を得るシェルスクリプト例を示しておく。端末で epsoutline file.dvi とすると file.eps が生成される。

#!/bin/sh
# convert dvi to outline eps
DVIPS="dvips -Ppdf -E -D 10000"
GS="gs -dNOPAUSE -dBATCH -sDEVICE=epswrite -r10000"
if [ $# -lt 1 ]; then
    echo "usage: `basename $0` dvifile"
    exit
fi
BS=`basename $1 .dvi`
echo "** making outlined EPS from $1"
$DVIPS $1 -o $BS-tmp.eps
$GS -sOutputFile=$BS.eps $BS-tmp.eps
rm -f $BS-tmp.eps
if [ $? -eq 0 ]; then
    echo "** output $BS.eps."
fi

参考文献

PDF が主流になったとはいえ,LaTeX フォントは Type1 PostScript が多いし,Ghostscript のフォントの扱いについても,Adobe による PostScript リファレンスマニュアルが役に立つ。日英の PDF 電子版 CD-ROM も添付されているので,PC に入れて持ち運ぶことも出来る。