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

2012/03/21
2012/03/27 追加
2012/04/15 追加

第一「いろは」問題

問題の提起

ここで言う、第一「いろは」問題とは、次の Tcl/Tk で書かれたプログラム a.tcl が生成する EPS ファイルを修正して、このプログラムの指示どおりのPDF ファイルを作成問題である。

この問題の要点は「いろは」をヒラギノ角ゴシックフォント(W6)で表示させる部分である。

a.tcl
この問題に対する解決の現状は以下の通りである。番号は問題の易しさの順に付けられている。
  1. そもそも Canvas に「いろは」が表示されない。
  2. Canvas には表示できるが、a.eps から PDF ファイルが生成されない。
  3. a.eps から生成された PDF ファイルには「いろは」は表示されない。

ここではヒラギノフォントを例に出したが、他の日本語フォントに関しても同様である。 なお、Tcl/Tk で使うフォント名は

font families
を wish で実行すれば得られる。詳しくは「Tcl/Tk Postscript の日本語フォントの問題(1)」に解説されている。そこで、以下では最初のレベルは解決されていると仮定する。

Tcl/Tk の postscript 出力で日本語フォントが使えない問題を解決する事の重要性は議論の余地がない。Python/Tk、ruby/Tk、perl/Tk など、多くの汎用言語は、postscript ファイルの生成に Tcl/Tk を利用しているからである。

第一「いろは」問題、Tcl/Tk が抱えている問題を完全に解決するものではない。プログラム a.tcl から生成された a.eps に手を加えて、「いろは」を表示させる問題なので、解決にはなっていないが、問題の原因をとらえる事ができ、解決へ向けて一歩前進するに違いない。

環境

a.eps から PDF ファイル a.pdf を生成するために何を使うか?
筆者の環境は Mac/OSX 10.6.8 (Snow Leopard) である。この環境では、考えられるのは

の2つである。他方、PDF ファイルを見るのには がある。( )内はバージョンであり、いずれも現時点では最新バージョンである。また Tcl/Tk のバージョンは 8.5.7 であった。Tcl/Tk のバージョン確認方法は「Tcl/Tk Postscript の日本語フォントの問題(1)」に書かれている。

解法

a.eps に次の2つの修正を加える。

修正点1

日本語フォントを指定した場合に type check error が発生するが、このエラーは ISOEncode から発生する。 全てのフォントに対して、機械的に ISOEncode が実行されているのである。 そこで、ISOEncoding を無効にする。

の後に

/ISOEncode {} def
を追加する。

修正点2

を次のように変更する。

以上の修正を行った a.eps を a1.eps とする。

結果

コマンドのメッセージを省略した。

注意: a1.pdf をマウスでクリックしてはならない。Preview.app が起動されて、転ける。コマンドから Adobe Reader を起動したのは、Preview が起動されるのを避けるためである。Preview.app は不安定で、今回の問題解決の利用には向かない。

Adobe Reader で見る a1.pdf

第二「いろは」問題

問題の提起

2012/03/27 追加

第二「いろは」問題とは、「いろは」をキャンバスに書き出す Tcl/Tk のプログラムで、キャンバスから生成された EPS ファイルに、修正を加えないで、 PDF ファイルを作成する問題である。

Tcl/Tk 8.5.11 のソース

Tcl/Tk のソースコードが必要になる。 Tcl/Tk の配布元 www.tcl.tk に置かれている Tcl/Tk の最新の安定バージョンは 8.5.11 である。(8.5.7 は置いてない。)

なおベータバージョンは、8.6b2 である。ここでは 8.5.11 を使う。

コンパイル

現在の Tcl/Tk のコード(8.5)は 64bit には対応していないらしく、32bit でコンパイルしなくてはならない注1

コンパイルの実行中のメッセージに注意: Tcl も Tk も -arch i386 のコンパイルオプションが付いている。例えば

  gcc -c -Os -arch i386 .....

コンパイルの結果は次のディレクトリにインストールされた。

/usr/local/bin
/usr/local/lib/tk8.5
/Library/Frameworks/Tcl.framework
/Library/Frameworks/Tk.framework

この事は、ファイルの生成時刻でも分かるが、もっと正当には次のコマンドから分かる。

-bash$ /usr/local/bin/tclsh
% puts $tcl_patchLevel
8.5.11
% puts $tcl_library
/Library/Frameworks/Tcl.framework/Versions/8.5/Resources/Scripts
% 
なお、標準的にインストールされている Tcl/Tk 8.5.7 は、以下のディレクトリに関係している。
/usr/bin
/usr/lib
/System/Library/Frameworks/Tcl.framework
/System/Library/Frameworks/Tk.framework

追記: /usr/local へのインストールは、多分、X11 版であろう。これは $tk/unix をコンパイルしてインストールした結果、生成されたと思われる。(生成時刻から判断)

注1:http://coding.derkeiler.com/Archive/Tcl/comp.lang.tcl/2009-10/msg00716.html

コンパイル時のトラブル

複数のバージョンのコンパイルは混乱をもたらす。互いに干渉し合うのである。

僕のケースでは $HOME/srctcl8.5.11tk8.5.11 を置いている。他のバージョンも同じように $HOME/src に置かれている。この場合 Tcl/Tk はコンパイル時に

$HOME/src/build/
を作り、バージョン間で共有される。これが問題をもたらす。確実にコンパイルしたいならは、これを削除してから行う必要がある。

Tcl/Tk は

sudo make install
で、何故か、一番新しいリソースにもアクセスが入る。僕の場合には、8.5.11 で 8.6b2 の存在が問題ももたらした。 そこで、これを防ぐために、tcl8.6b2tk8.6b2tcl8.6b2-tk8.6b2- になどにリネームして問題を回避した。

実行時の注意

今度は /usr/local/bin/wish を実行しなくてはならない。

Tcl/Tk 8.5.11 の問題点と解決法

Tk 8.5.11 では日本語フォントを ASCII 文字で指定できない。例えば、次のように書かなくてはならない。

そして生成された c.eps のヘッダは

のように、フォント名に日本語文字が使われる。しかし、どうやら、gs 9.05 では、日本語文字を含むフォント名に対応していないようだ。解決には、Tk の postscript 出力で fontmap を行う以外はなさそうである。

「いろは」を書き出すプログラム (d.tcl)

このプログラムでは「ヒラギノ角ゴ Pro W6」が HiraKakuPro-W6 として d.eps に書き出される。

問題のコードの場所

$tcl$tkを、各々 Tcl と Tk のソースコードが置かれているディレクトリとする。僕の場合には
tcl=$Home/src/tcl8.5.11
tk=$Home/src/tk8.5.11
である。「いろは」問題に関係しているファイルは次の2つである。
$tk/library/mkpsenc.tcl
$tk/generic/tkFont.c

$tk/library/mkpsenc.tcl の修正

ここでは単純に ISOEncode を無効にする。
mkpsenc.tclKenarと書いた行を挿入する

$tk/generic/tkFont.c の修正

tkFont.c の中の 関数 Tk_TextLayoutToPostscript の中の次のコードを修正する。
mkpsenc.tclKenarと書いた行を挿入する

説明が要求されるであろう。 ヒラギノフォントなどの日本語フォントの場合、Tk_TextLayoutToPostscriptglyphname を見つけられないでいる。そこで、glyphname の代わりに UTF8 文字列を使って [(いろは)] と EPS ファイルに書き出そうと言うわけである。そこで glyphname が見つからなかった場合の対応を加えたのが、ここでの修正である。

結果

今回は a.eps より、もう少し複雑な実験プログラム e.tcl を動かしてみよう。a.tcl では「ABC & いろは」を「ヒラギノ丸ゴ Pro」で表示させている。
実験プログラム e.tcl
この下で次のコマンドを実行する。
  /usr/local/bin/wish e.tcl
  ps2pdf -dEPSCrop e.eps
  open -a "/Applications/Adobe Reader 9/Adobe Reader.app" e.pdf
ps2pdf が 「HiraMaruPro-W4」を扱えるには Ghostscript の設定が必要である。
Adobe Reader による e.pdf の表示

残された問題点

ISOEncode

全てのフォントに対して ISOEncodeを無効にしたが、上位互換性を追求すべきである。このままではヨーロッパの言語に対して問題が発生する。

glyphname

glyphname が見つけられない問題に対して、ちゃんとした解決を考えるべきである。

fontmap

Tcl/Tk postscript のフォントマップの使い方は窮屈である。この窮屈さは Python/Tk では堪え難いものとなるだろう。フォントマップに頼らない方法が欲しい。EPS 出力では、postscript 名が使われるべきだと思う。

追記

2012/04/15

問題の箇所は Tcl/Tk postscript が生成した EPS ファイルに現れる次のコードである。

/HiraginoKakuGothicPro-Bold findfont 30 scalefont ISOEncode setfont
CMAP フォントに対しては ISOEncode を実行したくないのであるが、次のように書けば良いようだ。
/ISOEncode {dup /CMap known {} {ISOEncode1} ifelse} def

/ISOEncode1 {
    dup length dict begin
	{1 index /FID ne {def} {pop pop} ifelse} forall
	/Encoding CurrentEncoding def
	currentdict
    end

    % I'm not sure why it's necessary to use "definefont" on this new
    % font, but it seems to be important; just use the name "Temporary"
    % for the font.

    /Temporary exch definefont
} bind def
今度は ISOEncode は潰さない。