Tcl/Tk Postscript の日本語フォントの問題(1)

2012/03/04
2012/03/14 改訂
2012/03/17 改訂

Python/Tk の postscript() で生成された EPS が日本語フォントの文字を表示しない。問題の起源は Tcl/Tk にある。


2013/10/22 追記
結局僕は Python/Tk を使って日本の文字を含むグラフィックスを作る方法を見限ることとした。現在は SVG を利用した方がずっと簡単に、しかも良い結果が得られるからである。
詳しくは Python SVG Library を見てください。

キャンバスに「いろは」

バージョンの確認

僕の環境では Tcl/Tk のバージョンは 8.5.7 である。Tcl/Tk のバージョンは次のようにして分かる。

Tcl と Tk のバージョンは一致しているはずである。一致していなければ、何かがおかしい。

注意: www.tcl.tk で公開されている Tcl/Tk の最新バージョンは 8.5.11 である。パッチレベルが上がっているが、この違いは実は大きい。単なるバグ修正ではないようだ。以下の話は 8.5.7 での実験を基にしている。8.5.11 では、日本語フォントの名前に、漢字や仮名を使うので、ここで書いた事が大幅に修正される。

「いろは」を書き出すサンプルプログラム

この下で次のプログラム a.tcl を実行する。

このプログラム a.tcl は次のキャンバスを生成する。

a.tcl が描くキャンバス
このプログラムは確かに、「ABC」を Times italic で、「いろは」をヒラギノ角ゴPro-W6 で描いている。

このプログラムにおいては、フォント名(正確にはフォントファミリー名)をプログラムの中で、どのように指定するかが重要である。 Tcl/Tk が認識するフォントファミリーは次のようにして分かる。

Tcl/Tk が認識するフォント

wish で
font family
を実行すれば分かるが、次の方が見やすい。

結果は僕の環境(Tcl/Tk 8.5.7)では以下の通りである。

この中では "Hiragino Kaku Gothic Pro" となっている。これを使って不都合が発生すれば、Tcl/Tk に問題があると主張できる。

なお http://www.tcl.tk/man/tcl8.6/TkCmd/font.htm には、さらに気が利いたものがある。

バージョンによってフォント名の書き方が異なるのは問題である

Tcl/Tk 8.5.11 では、「Hiragino Kaku Gothic Pro」 ではなく、「ヒラギノ角 Pro W6」である。Tcl/Tk 8.4.19 でも同様に「ヒラギノ角 Pro W6」である。そのために a.tcl の中の 「Hiragino Kaku Gothic Pro」は Tcl/Tk 8.5.7 では正しいが、Tcl/Tk 8.5.11 や Tcl/Tk 8.4.19 では誤りで、正しいフォントで表示されない。これらの版では「ヒラギノ角 Pro W6」と書かなくてはならない。また逆にフォント名を「ヒラギノ角 Pro W6」で指定した場合には Tcl/Tk 8.5.7 では正しく表示されない。

フォント名に別名の概念はないのだろうか? アジアの複雑な文字のフォントは ASCII 文字による別名を持っていた方が扱いやすいと思うのだが...
例えば、「ヒラギノ角 Pro W6」の別名は「Hiragino Kaku Gothic Pro」であるとか...

生成された EPS ファイルのフォント

Postscript 名になっていない

プログラム a.tcl は「終了」ボタンで終了した時に、キャンバスを描く postscript のプログラム a.eps を書き出すようになっている。a.tcl が生成した a.eps を Mac の Preview.app で見ても「いろは」が表示されない。a.eps はテキストファイルである。そのヘッダ部は次の通りである。

a.eps のヘッダ部
a.eps は、フォント名が HiraginoKakuGothicPro-Bold に置き変わっている。

Mac のフォントブック(Font Book.app)には、「ヒラギノ角ゴ-W6」の postscript 名は HiraKakuPro-W6 であると書かれている。それにも係わらず、Tcl/Tk は HiraginoKakuGothicPro-Bold に置き換えた。この名前の生成規則は単純に、Tk のプログラムで指定されたフォントファミリー名の中の空白を除去し、「Bold」とハイフンで繋いだだけだと思われる。

こうした現象は Tcl/Tk が、日本語フォントに対応する postscript フォント名を知らないからであろう。それでは a.eps の中に現れる LucidaGrande-Bold を全て HiraKakuPro-W6 置き換えたらどうか? テキストエディタで置き換えてみたがダメである。Mac の Preview.app はやはり何も出力しない。

postscript 命令の fontmap オプション

Tcl/Tk の canvas の内容を書き出す postscript 命令は fontmap オプションを備えている。これが使えるか? 多分、これは、このような場合のためにあるのだ。Tcl/Tk のマニュアルに、このオブションについて説明はされているが、しかし分かりにくい。ネットで調べて見ると、「わからな~~い。教えて---」の声が結構見られるが、どうやら答えて貰えていない。そこで、この問題から片付ける。

fontmap を使ったプログラムの例 (b.tcl)
このプログラムの意図は、canvas の中で、「ABC」を Times で、「いろは」を「"Hiragino Kaku Gothic Pro" 30 bold」で表示し、postscript の出力(b.eps)では、「ABC」を Helvetica で、「いろは」を HiraKakuPro-W6 で表示させようと言う訳だ。 どの程度旨く行っているかを見るために、canvas と、b.eps を PDF 変換した結果を比較する。
canvas 画面と PDF変換との比較

Times は Helvetica に変換できたが、「"Hiragino Kaku Gothic Pro" 30 bold」は 成功していない。しかし、生成された EPS ファイルのヘッダ部では確かに成功しているのである。

b.eps のヘッダ部
fontmap に成功しているのがわかる
注意: 僕は fontmap で、文字サイズ情報が指定される事に、頭の中がパニックに陥った。そんなの、まともな仕様ではない! 四苦八苦したあげく、Tk を書いたプログラマの立場に立って考えてみて、ようやく fontmap の使い方が見えてきた。なまくらをしたと言うか、安全策を採ったのである。 canvas の中の文字の個々のフォント指定をそのまま、postscript の fontmap で変換しようと言う訳である。

b.eps のコードを見ると...

b.eps のコードの中の、文字を書き出している箇所をみてみよう。

b.eps の「ABC」と「いろは」を書き出す部分。 「いろは」が消えている!

フォントマップの効果によって、Times が Helvetica に、"Hiragino Kaku Gothic Pro" が HiraKakuPro-W6 に置き換わっている。フォントマップを行わなければ、置換はない。ここまでは期待していた通りである。

すぐに目につく問題点は、

  [(いろは)]
となるべき箇所が、
  [()]
となっていることである。(正確に言えば、b.eps のヘッダに、Clean7Bitと書かれているので、「いろは」を7bit にエンコードした情報と言うべきでしょう。 )

少し実験をしてみる。まず率直に、ここに「いろは」を入れる。もちろん「いろは」は表示されない。そんなに甘くはない。文字化けする。

文字化けしたフォントをよく見ると、Courier になっているらしい。実際に、これを Adobe Reader で確認すると Courier だと言う事が分かる。gs でもそうであるが、指定されたフォントが存在しない場合には、PDF ビューアはよく似たフォントで代用しようとする。全く分からない時には Courier で置き換える。つまり Preview.app は HiraKakuPro-W6 の代わりに Courier を使ったのである。a.eps では HiraginoKakuGothicPro-Bold となっているが、やはり Courier に置換されている。

b.eps の中の「いろは」を 「DEF」で置き換えると、ちゃんと Courier で「DEF」を書き出す。

以上から、Tcl/Tk の postscript 出力には2つの問題があると言う事が分かる。
(1) 日本語文字が出力コードの中から消える事。これはバグであろう。
(2) Preview.app が読み取れるフォント形式。これは多分、名前だけの問題ではないであろう。