Tcl/Tk で作った EPS ファイルは Mac (OSX 10.6) の Preview.app では何故か扱えない。Preview.app はメッセージを出さないので手がかりがつかめない。原因を探るのは絶望的である。そこで gs ではどうか?
詳しくは
Tk Postscript の日本語フォントの問題
を見よ。
僕は、gs の環境を整備して来なかった。これまでは Mac の Preview.app で間に合っていたから...
問題点
Ghostscript 9.02 が動いている。
「ABC」の問題は Helvetica の代用として NimbusSanL-Regu が使われたことが原因だと思われる。「いろは」の問題は HiraKakuPro-W6 を認識せずに、勝手に Courier で置換したから。
メッセージの中の
%rom%Resource/Font/NimbusSanL-Regu %rom%Resource/Font/HiraKakuPro-W6 の %rom% とは何か?僕の環境では NimbusSanL は次の場所にあった。
/usr/local/share/ghostscript/8.63/Resource/Font/この結果と比較すると
%rom%
とは /usr/local/share/ghostscript/8.63/
の事と考えたくなるのだが、他方では
の表示をみていると、違うかも...
なお、gs -h で表示された Search path のうち、僕のシステムで実際に存在するのは、
/usr/local/share/ghostscript/9.02/lib /usr/local/share/ghostscript/fonts /usr/share/cups/fontsだけで、このうち
/usr/share/cups/fonts
は空である。なぜか/usr/local/share/ghostscript/9.02/Resource/
/usr/local/share/ghostscript/8.63/Resource/
念のため ghostscript を再インストール。最新版は ghostscript-9.05 であった。
http://www.ghostscript.com/download/gsdnld.html
今回は、「ABC」が大きく改善された。アウトラインフォントで描かれている!
しかし、相変わらず「いろは」は表示されない。
メッセージをみると、ghostscript 9.05 は、%rom%Resource/Font/ に HiraKakuPro-W6 が見つからないと言って諦めていない。OSX のシステムフォントを探し、見つけるのに成功している。しかし、どうした訳か、Loading に失敗している。何故、Loading に失敗するのか、理由を知る事が問題解決の鍵である。
相変わらず/usr/local/share/ghostscript/9.05/Resource
は存在せず、存在するのは
/usr/local/share/ghostscript/9.05/lib /usr/local/share/ghostscript/fonts /usr/share/cups/fontsだけであり、
cups/font
は空である。ダウンロードしたパッケージには Resource
が含まれ、その中には多数のフォント関連のファイルが存在し、期待していたのに... 何故インストールされなかったのか?パッケージのドキュメントには、必要とあれば自分でインストールせよと書かれている。そこで取りあえずインストール。インストールされた内容は以下の通り。
今回は CID 関係のディレクトリが含まれている。
Resource をインストールしても、状況は変わらない。
Loading HiraKakuPro-W6 font failed.である。
もう一つ気になるのは、
/usr/local/share/ghostscript/9.05/Resourceを追加したにも係わらず
gs a.epsを実行しても gs は、このディレクトリを調べに行った気配がない事である。
Loading NimbusSanL-Regu font from %rom%Resource/Font/NimbusSanL-Regu...に現れた %rom% とは何か?
ghostscript-9.05 のソースコード(ghostscript-9.05/obj/gsromfs1.c
)の中に “NimbusSanL-Regu
” が現れる。どうやら gsromfs1.c の中に、フォントファイル NimbusSanL-Regu がハードエンコードされているのだ。ここで「ハード」と言ったのは、ユーザ側からは変更できないと言う意味である。NimbusSanL-Regu だけではなく、多数のフォント名が、このファイルの中に見られる。従って、配布ファイルの中の Resource の部分が、gsromfs1.c の中の %rom% だと思われる。
改めて make の出力を見てみると、gsromfs1.c は ghostscript-9.05/Resource/
から自動生成されている。
こうして生成された gsromfs1.c は 15.5MB もある。
/usr/local/share/ghostscript/9.05/Resource/Init/Fontmapをみると、Fontmap.GS が参照されている。そこで
/usr/local/share/ghostscript/9.05/Resource/Init/Fontmap.GSをみるとフォントの alias として以下の行が書かれている。
/Helvetica /NimbusSanL-Regu ; /Helvetica-Oblique /NimbusSanL-ReguItal ; /Helvetica-Bold /NimbusSanL-Bold ; /Helvetica-BoldOblique /NimbusSanL-BoldItal ;つまり Helvetica は NimbusSanL-Regu に置き換えられる。
注意: ファイルだけを見れば、「なるほど...」となるのであるが、実は非常に分かりにくい。プログラムの中に alias に相当するコードが存在するのである。base/gdevpdtb.c
には次のテーブルがある。
/* Standard mapping of URW fonts */ {"NimbusMonL-Regu", "Courier" }, {"NimbusMonL-Bold", "Courier-Bold" }, {"NimbusMonL-ReguObli", "Courier-Oblique" }, {"NimbusMonL-BoldObli", "Courier-BoldOblique" }, {"NimbusSanL-Regu", "Helvetica" }, {"NimbusSanL-Bold", "Helvetica-Bold" }, {"NimbusSanL-ReguItal", "Helvetica-Oblique" }, {"NimbusSanL-BoldItal", "Helvetica-BoldOblique"},この他に、既に述べたように
obj/gsromfs1.c
の中にも、同様な情報が含まれている。(%tom%
はResource/Init/Fontmap.GSを取り込んでいるから...。)
こうした、ハードエンコードされた情報と、
/usr/local/share/ghostscript/9.05/Resource/Init/Fontmap.GSとの不一致が発生した場合の振る舞いが定かではないのである。なんで ghostscript を書いたプログラマはこんなヤヤコしい事をやるのだ? センスを疑う。もっとも彼らも、このスタイルが良いとは思っていないらしい。
bash$ grep Fontmap /users/arisawa/src/ghostscript-9.05/*/*.c /users/arisawa/src/ghostscript-9.05/base/gdevmsxf.c:/* This table should be an external resource, like Fontmap, */ /users/arisawa/src/ghostscript-9.05/obj/gsromfs1.c: /* file name 'Resource/Init/Fontmap' */ /users/arisawa/src/ghostscript-9.05/obj/gsromfs1.c: /* file name 'Resource/Init/Fontmap.GS' */ /users/arisawa/src/ghostscript-9.05/obj/gsromfs1_.c: /* file name 'Resource/Init/Fontmap' */ /users/arisawa/src/ghostscript-9.05/obj/gsromfs1_.c: /* file name 'Resource/Init/Fontmap.GS' */ /users/arisawa/src/ghostscript-9.05/psi/zfontenum.c: to the Fontmap to reference fonts stored on the system.
追記:
NimbusSanL-Regu は /usr/local/share/ghostscript/fonts/
にもある
n019003l.afm, n019003l.pfb, n019003l.pfm
と関係があるらしい。
bash$ grep NimbusSanL-Regu /usr/local/share/ghostscript/fonts/* /usr/local/share/ghostscript/fonts/n019003l.afm:FontName NimbusSanL-Regu Binary file /usr/local/share/ghostscript/fonts/n019003l.pfb matches Binary file /usr/local/share/ghostscript/fonts/n019003l.pfm matches /usr/local/share/ghostscript/fonts/n019023l.afm:FontName NimbusSanL-ReguItal Binary file /usr/local/share/ghostscript/fonts/n019023l.pfb matches Binary file /usr/local/share/ghostscript/fonts/n019023l.pfm matches /usr/local/share/ghostscript/fonts/n019043l.afm:FontName NimbusSanL-ReguCond Binary file /usr/local/share/ghostscript/fonts/n019043l.pfb matches /usr/local/share/ghostscript/fonts/n019063l.afm:FontName NimbusSanL-ReguCondItal Binary file /usr/local/share/ghostscript/fonts/n019063l.pfb matches bash$ edit /usr/local/share/ghostscript/fonts/n019003l.afm bash$
Loading HiraKakuPro-W6 font from /Library/Fonts/ヒラギノ角ゴ Pro W6.otf... 3531392 2173798 20393248 12769844 3 done. Loading HiraKakuPro-W6 font failed.ファイルは見つかって、それを読み取った。そして failed と言う事は、読み取った内容に問題があったと言う事であろう。
実際、gs が読み取ろうとしたファイルは拡張子の付かない HiraKakuPro-W6 であり(Resource/Font/
の中のファイルは、どれも拡張子が付いていない)、実際に読み取ったのは拡張子 otf
が付いたファイルである。形式が異なるかも知れない。
注記: Resource/Font/
の中のファイルはフォントファイルではないらしい。
Ghostscript compiled with the "ttfont" option can also use TrueType fonts with the extension .ttf.
ttfont
オプションを付けてコンパイルすれば True Type font が使えるって! しかし...ttfont
オプションが見えて来ない。僕は何か勘違いしているかも...
そもそも、gs が %rom% を参照するのが混乱の元なのだ。そこで、これを外せないかと思ってネット情報を調べていたら次のページが見つかった。
http://oku.edu.mie-u.ac.jp/~okumura/texwiki/
に、ghostscript 9.05 では configure
で、disable-compile-inits
のオプションを指定しないと cidmap を参照しないらしいと書いている。実際 9.05 のconfigureの内容を見ると、
と書かれている。この下でインストールをやり直したら、確かに %rom%
を参照しないで、/usr/local/share/ghostscript/9.05/Resource/
を見に行く。
以下は全て %rom% なしの gs を使った結果である。
Resource/Init
の中のFontmap.GS
とcidfmap
である。これらの役割をはっきりさせないと、いつまでも頭の名が ????? である。
久しぶりに 「PostScript Language Reference Manual」(Adobe Systems)を開いて、デバッグコードは
(Hello World) printのようにコードの中に挿入すればよろしい事が分かった。
( ) は Postscript では文字列である。この部分は「(Hello World) を print しなさい」と読む。語順は日本語と同じであるから日本人には分かりやすい。print の結果は標準出力に出る。
僕の Resource/Font
にはHiraKakuPro-W6-H
の内容は次のようになっていた。(このファイルはどこかから採ってきたものだ。)
これにデバッグコードを入れるには(例えば)次のようにすればよい。
こうして実験した結果によれば、Resource/Init/Fontmap.GS
には、
/HiraKakuPro-W6 /HiraKakuPro-W6-Hのような行を入れておかなくてはならない事がわかる。a.eps の中ではフォント名が HiraKakuPro-W6 で指定されている。従って、この行が無いと、gs は
Resource/Font/HiraKakuPro-W6
を探しに行って、存在しないと言う1。
gs 自体は HiraKakuPro-W6 が CID フォントである事を知らないのだから...
注1: 後に見るように、この言い方は正確ではない。gs は内部でフォント名の変換を行い、処理を行っている。
このケースでは gs は Resource/Font/HiraKakuPro-W6-H
を読み取って、次の行によって、初めて HiraKakuPro-W6 が CID フォントである事が分かる。gs は
[/HiraKakuPro-W6 /CIDFont findresource]によって、CIDFont の中の HiraKakuPro-W6 を読みに行こうとするのだが、その前に
Resource/Init/cidfmap
を見る。ここに HiraKakuPro-W6 の情報がなければ、そのまま
Resource/CIDFont/HiraKakuPro-W6
を読む。あれば、それに基づいて他のファイルを読もうとする。このへんの動作は Fontmap.GS
と同じなのであろう。ルーチンを再利用しない理由は無い。(と思ったのだが、実際には違うようである。実ファイルの場所を示す<< .... >>が必要らしい。
「ヒラギノ角ゴ-Pro-W6」を読み取らせるには2つの方法があるのだろう。
Resource/CIDFont/HiraKakuPro-W6
に「ヒラギノ角ゴ-Pro-W6.otf」のリンクを張る。
/usr/local/share/ghostscript/fonts
に HiraKakuPro-W6 の名で、代用するTrueTypeフォントへのリンクを張る。
cidfmap
は弄らない。cidfmap
に以下の1行を書き込む。
/HiraKakuPro-W6 << /FileType /TrueType /CSI [(Japan1) 6] /Path (ipagp.ttf) >> ;ここではIPAフォントで代用した。ここに直接 HiraKakuPro-W6 へのリンクを張ると
====== findresource: STARTED ====== Loading a TT font from /usr/local/share/ghostscript/fonts/HiraKakuPro-W6.otf to emulate a CID font HiraKakuPro-W6 ... Done. Error: /invalidfont in /findfontと表示される。
ちなみに IPA フォントで置き換えた場合、次のメッセージで終わる。
====== findresource: STARTED ====== ====== findresource: FINISHED ====== 19713816 12055061 3994944 2598670 3 done. Error: /typecheck in definefontこれは
findresource
を無事にパスし、その後で問題があった事を意味している。
追記: 僕の環境(OSX 10.6)には "Arial Unicode.ttf" があり、日本語が表示できる。これも IPA フォントと同様に、typecheck エラーとなる。
注意: Ghostscript のマニュアルには次のように書かれている。
Note that loading truetype fonts directly from /Resources/CIDFont is no longer supported
(ghostscript/9.05/doc/Use.htm)
であるから、ここに述べたTrueType フォントに大しては、第1の方法は使ってはならない。サポートを止めた理由は、gs の辞書に読み取るための十分な情報がないからだと言う。
日本語文字「いろは」を含む、Tcl/Tk で作った a.eps の表示に成功するか? 今のところ、No である。 これまでの実験によれば、使用するフォントによって、エラーメッセージには2つのパターンがある。"invalidfont" と "typecheck" である。前者は OpenType で、後者は TrueType で発生している。前者はフォントファイルの読み取りに失敗している。読み取ったはよいが、内容に不満があるのである。後者は、どうやら読み取った内容に不満は無いらしい。しかし確認が必要である。そのためには、もっと簡単なプログラムが必要である。
これは成功する。それではフォントを HiraKakuPro-W6 に置き換えて、「こんにちは」を書き出すのはどうか? もちろん、そんなに甘くはないと考えているが、問題解決のヒントにはなるだろう。
このプログラムは、エラーを吐き出さずに、正常終了する。 しかし、文字が化けている。正常終了するのは gs の中でのフォント変換によって、ttf フォントが指定された時である。
このことから3つの事が分かる。
PostScriptファイル内で指定するフォント名は、上で指定した/MS-Gothicの後ろに、ハイフンに続けてCMap名を付けたものになる。CMap名はResource/CMapにあるファイル名を指定すればよい。CMapは各文字の文字コードをCID・・・フォント内の字形の番号に変換する働きがあるので、CMap名で文字コードも決まる。( http://www.akamoz.jp/you/uni/gs-cyg-ttf.htm )
これによると僕の場合にはフォント名は
HiraKakuPro-W6-UniJIS-UTF8-H
である。
で実験。そして驚くべき事に、「こんにちは」が表示された。驚いたのは、Fontmap.GS
や cidfmap
を変更していないし、Resource/Font/
の中に、新たに何も追加していないまま試したからである。gs はどのようにして HiraKakuPro-W6-UniJIS-UTF8-H
を見つける事ができたのか?
僕の環境では Resource/Font/
の中には HiraKakuPro-W6
や HiraKakuPro-W6-H
が置かれている。これらは、実行された時にメッセージを吐き出すように修正されている。しかし、ここからのメッセージは観測されない。
あらためて Ggostscript 付属のドキュメントを読む。Fonts.htm
には次のように書かれている。
as part of normal initialization Ghostscript runs a file gs_fonts.ps,
そして、Resource/Init/gs_fonts.ps
を見ると、フォント名の置き換えらしきコードが多数存在するのである。こんなプログラムの作り方は嫌いだ~~~
プログラムを作る時にはユーザーズ・インターフェースに気を使う。ユーザーズ・インターフェースと言うのは、GUIのボタン等や、対話型プログラムのコマンドセットだけではない。設定ファイルも、また重要なインターフェースなのだ。ユーザの意思を無視したインターフェースは最悪のプログラムだと思う。現在の gs はそのような酷さがある。
さて我々の目標は、gs の設定に特化した k1.ps ではなく、一般的な postscript 名でフォントを指定した k.ps を gs で動かすことである。これまでの試行錯誤を行えば後は簡単である。まずは Resource/Init/Fontmap.GS
を次のように設定し、
Resource/Font/HiraKakuPro-W6-UniJIS-UTF8-H
に制御が移るようにする。
次にResource/Font/HiraKakuPro-W6-UniJIS-UTF8-H
を次の内容で作成する。
この中には print を含む行が3カ所にあるが、デバッグのためなので、後で消してもよい。
Resource/Init/cidfmap
で HiraKakuPro-W6 を実際のフォントファイルに関係させる。ここでは ArialUnicode.ttf
と関係付けている。
ArialUnicode.ttf
は
/usr/local/share/ghostscript/fonts
に置く。
注意: /CSI [(Japan1) 6] の部分はいい加減である。多分間違っているが、一応は「こんにちは」が表示される。
cidfmap の中に /HiraKakuPro-W6 のエントリーを書かない。あるいはせいぜい
/HiraginoKakuGothicPro-Bold /HiraKakuPro-W6 ;にとどめる。
Resource/CIDFont/
の中に「ヒラギノ角ゴ.otf」へのリンクを HiraKakuPro-W6 の名で張る。
あるいは、ここに、「ヒラギノ角ゴ.otf」をコピーして、HiraKakuPro-W6 と名前を変更してもよいが、管理上は(元が分かるように)リンクの方が僕の好みである。
/HiraKakuPro-W6 /HiraKakuPro-W6-UniJIS-UTF8-H ; /HiraginoKakuGothicPro-Bold /HiraKakuPro-W6-UniJIS-UTF8-H ;この意味は、Postscript コードで、左のフォント名が指定された時に、右のファイルの実行を指示する。右のファイルは
Resource/Fontに置く。
配布パッケージには
Resource/Font/HiraKakuPro-W6-UniJIS-UTF8-Hは存在しないので、次の内容で作成する。
gs -dEPSCrop k2.epsのように gs に d オプションで EPSCrop を指定する。PDF ファイルを生成するには
ps2pdf -dEPSCrop k2.epsとする。これで BoundingBox で指定されたサイズのPDFファイル、k2.pdf が生成される。これを gs で見るには
gs k2.pdfで、その結果は次のようになる。
Adobe Reader では(僕の環境では)
open -a "/Applications/Adobe Reader 9/Adobe Reader.app" k2.pdfとしなくてはならない。Adobe Reader へのパスを open で開かなくてはならない。コマンドを使わざるを得ないのは、Mac の Preview.app に問題があるからである。k2.pdf をマウスで選択すると、Preview.app がそれを開く。そして、転ける。 しかし、そうした問題があるにも係わらず Adobe Reader はちゃんと表示してくれる。イメージ形式の PDF ファイルではなく、文字として表示されている。大きく引き延ばしても、ギザギザにならない。
(A) 生成された k2.pdf は 500KB もある。これはヒラギノ角ゴの全てのフォントを埋め込んだ結果だと思う。必要な分だけの埋め込みを行ってくれれば、もっと小さくて済んだはずであるが、これは現在の gs の到達段階を示しているのだろう。
(B) k2.pdf は Preview.app を転けさせる。Preview.app は k2.eps の中の HiraKakuPro-W6 を認識しない。Courier に置き換えられる。
(C) 僕は、たぶん、手動で設定しすぎているだろう。不要な部分があるだろう。
/CSI [(Japan1) 6]
について(Japan1) 6
」は
Resource/CMAP/
の中の
Abode-Japan1-6
を指しているらしい。
このディレクトリの中には、これとよく似た名前のファイルが6つある。すなわち、
Adobe-Japan1-1,...,Adobe-Japan1-6
である。このファイルの役割は、文字コードとサポートされているグリフとのマッピング情報を提供しているらしい。そして、語尾の数字が大きい程、マッピング情報は多くなり、数字の大きいファイルは小さいファイルのスーパーセットになっている。これらのファイルはテキストファイルなので、内容を見る事が可能であり、実際、比較してみるとスーパーセットになっていることが分かる。
フォントファイルにとって、このような基本的な情報が、ファイルの内部に含まれていないらしい。(だから、ファイルを読み取る時に指定するのだろう。) では、我々はどこからこの情報を手に入れたらよいのだろうか?
IPAフォントの情報は
http://ossipedia.ipa.go.jp/ipafont/fontspec.htmlから手に入る。このフォントは「JIS X 0213:2004」に基づいていると言う。この規格の概要は
「JIS漢字コード表の改訂について」(経済産業省,平成16年2月20日) http://www.jisc.go.jp/newstopics/2005/040220kanjicode.pdfから手に入る。それによると、この規格では10040文字がサポートされている。
他方では Adobe-Japan1-3 は 9472 文字、
Adobe-Japan1-4 は 15616 文字のテーブルを持っているので、Adobe-Japan1-4 以上を指定しておけば大丈夫という事か?
何となく釈然としない。それなら一番大きな数字のもの(Adobe-Japan1-6)で何か不都合な事があるか?
「Arial Unicode MS」はどのように指定したらよいのか?
適当に設定して動いているのだが...