ワールドカップ出場記念で英語をいっぱい書いてみた
graphvizで日本語を出す話はいろいろ聞くけれど、にんとも上手く動かなかったのでいろいろやった、その結論。
あ、環境は
%uname -sr FreeBSD 5.4-RELEASE-p1 %pkg_info|fgrep graphviz graphviz-2.2 Graph Visualization Software from AT&T and Bell Labs %dot -V dot version 2.2 (Wed Jun 8 13:51:09 UTC 2005)
です。
書き方
UTF-8で書く。心配なら
digraph G { graph [charset="UTF-8"] }
とでもしておく。でもデフォルトがUTF-8だから、そこまでせんでも。
あと、日本語フォントを指定する。例えば
digraph G { 日本語 [fontname="mona"] }
フォントの指定
graphvizがfontconfigに対応している場合は"mikachan"とか"Sazanami Gothic"とか適当に指定する。
対応していない場合はフォントファイルを直接指定する。例えばみかちゃんフォントなら
%dot test.dot -Nfontname=mika -Nfontpath=/usr/X11R6/lib/X11/fonts/TrueType -Tpng
とやれば、/usr/X11R6/lib/X11/fonts/TrueType/mika.ttfを使ってくれる。
graphvizとfontconfig
graphvizはfontconfigに対応しているが、FreeBSDのportをそのまま使うとこれが有効にならない。
graphvizのconfigureはfontconfig-confというプログラムが見つかれば自力でfontconfigを発見するのだが、これはFreeBSDでは見つからない(そもそも存在するんだろうか?)。だからconfigureのオプションでfontconfigのヘッダーとライブラリの場所を直接教えてあげる必要がある。
面倒なのでportのMakefileを直接書き換えた:
*** Makefile.org Thu Jun 9 02:03:41 2005 --- Makefile Wed Jun 8 22:49:00 2005 *************** MLINKS= dot.1 circo.1 \ *** 51,56 **** --- 51,61 ---- MYPORTDOCS= dotguide.pdf dottyguide.pdf leftyguide.pdf \ neatoguide.pdf Dot.ref FAQ.html + .if defined(WITH_FONTCONFIG) + CONFIGURE_ARGS+=--with-fontconfigincludedir=${X11BASE}/include \ + --with-fontconfiglibdir=${X11BASE}/lib + .endif + post-install: .if !defined(NOPORTDOCS) @${MKDIR} ${DOCSDIR}
ちょっとかっこつけてWITH_FONTCONFIGで選択可能にしてみた :-)
で、これでmake WITH_FONTCONFIG=yesすればfontconfigに対応したgraphvizのできあがり。
この話はとりあえずfreebsd-questionsに投げてみた。問題なさそうならport maintainerに連絡したいな。
dotがカタカナで落ちる問題
さて、これでばりばり日本語のグラフを作っていたら、いくつかdotがクラッシュするものが見つかった。某所では「GDかiconvのバグ」と出ていたけど、調べたらどうやらdotのバグらしいことが分かった。
以下は御本家に出したバグレポート:
Title: Memory exhaust with UTF-8 Japanese Katakana
Description of problem:
Using japanese katakana(U30A0-U30FF) characters causes memory exhaust in label_size() in dotneato/common/labels.c.
label_size() function has a workaround for Big5 charset and it makes some input characters skip when their codes are in range 0xA1-0xFE.
Unfortunately, japanese katakana characters are represented as byte sequence 0xE382A0-0xE383BF in UTF-8, some of their last byte in the range above.
So the workaround casts head position of input (variable p) over the null-terminator, then the while loop will go infinite.
This problem would happen in other than japanese katakana characters, but I haven't checked.Fix:
The following patch works fine for me:*** dotneato/common/labels.c Thu Jun 9 00:53:40 2005 --- dotneato/common/labels.c.new Thu Jun 9 00:53:31 2005 *************** static pointf label_size(char *str, text *** 60 **** --- 61 ---- + size_t len; *************** static pointf label_size(char *str, text *** 67 **** ! line = lineptr = N_GNEW(strlen(p) + 1, char); --- 68 ---- ! line = lineptr = N_GNEW(len = strlen(p) + 1, char); *************** static pointf label_size(char *str, text *** 69 **** ! while ((c = *p++)) { --- 70 ---- ! while (p < str + len && (c = *p++)) {
ちなみに問題が起こるのは、UTF-8で任意のカタカナ5文字をラベルに使ったとき。前後に1文字でも追加すれば問題は起こらない。びみょー。
今気が付いたけど、メモリが尽きるんじゃなくて変なメモリを読みに行くバグだな。あちゃあ。