macOS Sierra Ghostscript 9.21 アウトライン EPS の生成

macOS Sierra TeX Live 環境を整備する一環として,アウトライン EPS (Encapsulated PostScript) を生成するための Ghostscript 調整を試みた。Ghostscript は過去二十年以上にわたってオープンソースの PostScript インタープリタとして定番となっているコアなソフトウェアである。

フォント埋め込みの PDF でも埋め込みフォントデータの問題で印刷所のイメージセッタにかけると文字化けを起こす場合がある。こういうとき文字をベクトル画像にしたアウトライン EPS を作成し,これを文書に挿入することにより問題回避できるので,アウトライン EPS を得る手段は備えておきたい。これまで,LaTeX,dvips で生成した EPS からアウトライン EPS を作成するのに Ghostscript は欠かせない存在だったのである。一方で,日本語フォントを扱うに面倒な調整が必要なソフトウェアでもある。MacPorts でパッケージを入れまくった過程で Ghostscript 9.21 がすでにシステムに導入されていたので,これを調整することとした。MacPorts でインストールする場合,sudo port install ghostscript を端末から実行すればよい。

ところが,macOS の日本語フォントであるヒラギノは,いつのころからか otf フォントから ttc フォントに変更されていて,Ghostscript は ttc をサポートしていないことが判明。高品質なヒラギノフォントが使えない文書作成アプリケーションは macOS ではほとんど使い物にならない。Ghostscript はもう使えないのかとたいへん残念に思った。日中韓フォント調整は諦めるか。

しかしながら,いろいろ試すうちに,Ghostscript eps2write デバイス,-dNoOutputFonts オプションを用いることで,dvipdfmx で生成したフォント埋め込みの PDF から,文字がアウトライン化された EPS が得られることがわかった。しかも,日本語フォント調整をしなくても,インストールしたままの未調整の Ghostscript でこれが可能なのである。従来 EPS ファイル出力用のデバイスは epswrite という名称だったが,Ghostscript 9.21 では eps2write に変更されていた。

以下のような,多様な文字種からなる多言語 LaTeX 原稿 gscjkfont.tex を用意して,試験してみた。数式,日本語,ロシア語,教会スラヴ語,複式アクセント付古典ギリシア語,ニクダ付古代ヘブライ語,簡体中国語,繁体中国語,韓国語,タイ語,ヴェトナム語からなるテクストである。ここで,教会スラヴ語は弊サイトが提供する OldSlav パッケージを利用している。日本語用の Babel 言語定義も OldSlav に同梱されている。本サンプルを TeX Live 2017 でタイプセットするには OldSlav を組み込んでおく必要がある。macOS Sierra TeX Live 2017 を参照。

% -*- coding: utf-8; mode: latex; -*-
% gscjkfont.tex - Ghostscript CJK フォント試験
\documentclass[b5paper]{jsarticle}
\usepackage[utf8x]{inputenc}%
\usepackage{lmodern}%
\usepackage[T2A,T1]{fontenc}%
\usepackage[thai,vietnamese,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{vietnamese}%
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}

この原稿を ptex2pdf (日本語 LaTeX) で処理してフォント埋め込み PDF を生成し,次に gs (Ghostscript) でこの PDF をアウトライン EPS に変換する。このとき,ptex2pdf の裏方として動作する dvipdfmx はヒラギノフォント埋め込み指定のフォントマップが使われる設定となっている必要がある(そのためのマップ設定はここでは割愛)。また,生成した EPS に余計な余白が付かないよう,\pagestyle{empty} をプレアンブルで設定しておくのがよい。

$ ptex2pdf -l gscjkfont.tex
$ gs -dNOPAUSE -dBATCH -sDEVICE=eps2write -r10000 -dNoOutputFonts \
   -sOutputFile=gscjkfont.eps gscjkfont.pdf

ここで,-sDEVICE=eps2write の部分は,以前の Ghostscript バージョンでは -sDEVICE=epswrite としなければならないだろう。-dNoOutputFonts オプション指定がアウトライン化のもうひとつの肝である。このオプションがない以前のバージョンでは -dNOCACHE オプションを指定すればよいようである。参考までに,インプットとなる gscjkfont.pdf と,生成された gscjkfont.eps をリンクしておく。

こうして生成された gscjkfont.eps は,文字がすべてアウトライン化されたベクトルイメージとなっている。epstopdf --filter < gscjkfont.eps > work.pdf として生成した work.pdf を Adobe Reader で開いてフォントプロパティを確認すると,下図のとおり,フォント情報がなくすべて画像となっていることがわかるだろう。この画像はモニタのスクリーンショットであるため文字が汚く見えるけれども,実際はベクトル画像なので,拡大してもギザギザのない美しい印刷出力が得られる。このアウトライン EPS の LaTeX 文書への取り込みは,graphicx パッケージの \includegraphics 命令で行う。

20170923-gsoutline.png
アウトライン化の確認

フォント埋め込み PDF ファイルを引数に取り,ファイルベース名.eps のファイル名でアウトライン EPS ファイルをカレントディレクトリに出力するシェルスクリプトの例を以下にあげておく。

#!/bin/sh
# pdf2eps: フォント埋め込みPDFからアウトラインEPSを生成する。
# usage: pdf2eps pdf
# notice: for Ghostscript 9.21
 
GS=/opt/local/bin/gs
OP="-q -dNOPAUSE -dBATCH -sDEVICE=eps2write -r10000 -dNoOutputFonts"
# 以前のバージョンでは以下にする必要があるかも知れない
# OP="-q -dNOPAUSE -dBATCH -sDEVICE=epswrite -r10000 -dNOCACHE"
 
if [ $# -ne 1 ]; then
	echo 'usage: pdf2eps pdf'
	exit 1
fi
 
BN=`basename $1 .pdf`
$GS $OP -sOutputFile=$BN.eps $1
echo "pdf2eps generated outlined EPS: $BN.eps"
exit 0