wxWidgets アプリを Lua で記述する wxLuaApp。これで PDF を作成したいと思ったのだが、wxWidgets には PDF 関連の API がない。誰か作ってるでしょ、と「Lua PDF」で検索すると、「Lua 関連の PDF 文書」が大量にヒットして、なかなか有益な情報にたどりつかない。PDF 関連の情報をネット検索で探すのは、案外面倒なんですね。
「Lua PDF create」で探して出てきた、LuaHPDF が良さげだったので、試してみた。
「Haru Free PDF Library」の Lua バインディングらしい。そうか、このライブラリは前に一度調べたことがあったな。オリジナルの作者が日本人なので、日本語対応がちゃんとしている。これは大事なポイントです。
使い方の方針を決めておかないといけない。今回は、Lua スクリプトから見える場所に hpdf.dylib
(Mac) または hpdf.dll
(Windows) を置いて、hpdf = require "hpdf"
で読み込むようにする。動的ライブラリは1個だけにしたいので、libHaru は静的にリンクすることにする。
まず libHaru と luaHPDF をダウンロードする。
$ curl -L https://github.com/libharu/libharu/archive/RELEASE_2_3_0.zip >libharu-RELEASE_2_3_0.zip
$ unzip libharu-RELEASE_2_3_0.zip
$ curl -L https://github.com/jung-kurt/luahpdf/archive/master.zip >luahpdf-master.zip
$ unzip luahpdf-master.zip
ここで大事なお知らせ。libHaru は libpng, zlib に依存します。Mac では、zlib はシステム標準のものを使う。libpng は X11 関連のライブラリにあるが、インストールされていない可能性もあるので、自前でビルドして静的リンクする。Windows では、両方自前でビルドすることにする。libHaru, luaHPDF と同じ階層に、libpng_zlib
というディレクトリを作って、その中に zlib, libpng をインストールする。
$ mkdir libpng_zlib
$ cd libpng_zlib
$ curl -L https://download.sourceforge.net/libpng/libpng-1.6.37.tar.gz >libpng-1.6.37.tar.gz
$ tar xzf libpng-1.6.37.tar.gz
$ curl -L https://www.zlib.net/zlib-1.2.11.tar.gz >zlib-1.2.11.tar.gz
$ tar xzf zlib-1.2.11.tar.gz
Mac 用のビルド。libpng を libpng_zlib/build-osx
にインストールする。SDK として /Developer/SDKs/MacOSX10.6.sdk
を指定する。--disable-shared
と --enable-static
を指定して、静的ライブラリのみ作成する。
cd libpng-1.6.37
$ CFLAGS="-isysroot /Developer/SDKs/MacOSX10.6.sdk" CPPFLAGS="$CFLAGS" ./configure --prefix=$PWD/../build-osx --disable-shared --enable-static
$ make
$ make install
libHaru のビルド。これも静的ライブラリのみ作成する。
$ cd ../../libharu-RELEASE_2_3_0
$ export SDK=/Developer/SDKs/MacOSX10.6.sdk; CFLAGS="-isysroot $SDK" ./configure --prefix=$PWD/build-osx --disable-shared --enable-static --with-sysroot=$SDK --with-png=$PWD/../libpng_zlib/build-osx --with-zlib=$SDK/usr
$ make
$ make install
luaHPDF のビルド。ファイル1個だけなので、Makefile を書くより手打ちの方が早い。LuaJIT は、wxLuaApp の中でビルドしたものをリンクする。
$ cd ../luahpdf-master
$ gcc -isysroot /Developer/SDKs/MacOSX10.6.sdk -I../wxLuaApp/LuaJIT-2.0.5/src -I../libpng_zlib/build-osx/include -I../libharu-RELEASE_2_3_0/build-osx/include -Wall -O2 -fomit-frame-pointer -fPIC -c -o hpdf.o hpdf.c
$ gcc -shared -fPIC -isysroot /Developer/SDKs/MacOSX10.6.sdk -o hpdf.dylib hpdf.o -L../wxLuaApp/build-xcode/build/lib -L../libpng_zlib/build-osx/lib -L../libharu-RELEASE_2_3_0/build-osx/lib -lhpdf -lz -lpng -lm -lluajit-5.1
できた!
$ ls -l *.dylib
-rwxr-xr-x 1 nagata staff 1176140 8 29 23:28 hpdf.dylib
試してみる。
package.cpath = "./?.dylib;" .. package.cpath
hpdf = require "hpdf"
local pdf = hpdf.New()
local page = hpdf.AddPage(pdf)
local height = hpdf.Page_GetHeight(page)
local width = hpdf.Page_GetWidth(page)
local font = hpdf.GetFont(pdf, "Helvetica")
hpdf.Page_SetFontAndSize(page, font, 24)
hpdf.Page_BeginText(page)
hpdf.Page_TextOut(page, 60, height - 60, "Hello from Haru")
hpdf.Page_EndText(page)
hpdf.SaveToFile(pdf, "hello.pdf")
hpdf.Free(pdf)
できました。
次は Windows (64 bit) のビルド。zlib でちょっと手こずった。
$ cd path/to/libpng_zlib
$ cd zlib-1.2.11
$ CHOST=x86_64-w64-mingw32 ./configure --prefix=$PWD/../build-win --static
...
Please use win32/Makefile.gcc instead.
えー、大きなお世話じゃ。win32/Makefile.gcc
は 32bit 限定なので、64bit 版はビルドできない。仕方がないので、configure
に手を入れた。
MINGW* | mingw*)
# temporary bypass 次の3行をコメントアウト。
#rm -f $test.[co] $test $test$shared_ext
#echo "Please use win32/Makefile.gcc instead." | tee -a configure.log
#leave 1
再トライ。今度はうまくいった。
$ CHOST=x86_64-w64-mingw32 ./configure --prefix=$PWD/../build-win --static
$ make
$ make install
次は libpng。CFLAGS
と CPPFLAGS
を両方指定しないといけない。気づくのに時間がかかった…
$ cd ../libpng-1.6.34
$ CFLAGS="-L$PWD/../build-win/lib" CPPFLAGS="-I$PWD/../build-win/include" ./configure --prefix=$PWD/../build-win --host=x86_64-w64-mingw32 --disable-shared --enable-static
$ make
$ make install
libHaru は特に問題なし。
$ cd ../../libharu-RELEASE_2_3_0
$ ./configure --prefix=$PWD/build-win --host=x86_64-w64-mingw32 --disable-shared --enable-static --with-png=$PWD/../libpng_zlib/build-win --with-zlib=$PWD/../libpng_zlib/build-win
$ make
$ make install
luaHPDF のビルド。前に書いた通り、fopen
をマルチバイト対応のものに置き換える必要があるので、win_fopen.o
を作成してリンクする。
$ x86_64-w64-mingw32-gcc -I../wxLuaApp/LuaJIT-2.0.5/src -I../libpng_zlib/build-win/include -I../libharu-RELEASE_2_3_0/build-win/include -Wall -O2 -fomit-frame-pointer -fPIC -c -o hpdf.o hpdf.c
$ x86_64-w64-mingw32-gcc -I../wxLuaApp/LuaJIT-2.0.5/src -I../libpng_zlib/build-win/include -I../libharu-RELEASE_2_3_0/build-win/include -Wall -O2 -fomit-frame-pointer -fPIC -c -o win_fopen.o win_fopen.c
$ x86_64-w64-mingw32-gcc -shared -fPIC -o hpdf.dll hpdf.o win_fopen.o -L../wxLuaApp/build-win/build/lib -L../libpng_zlib/build-win/lib -L../libharu-RELEASE_2_3_0/build-win/lib -lhpdf -lpng -lz -lm -llua51
できた。
$ ls -l *.dll
-rwxr-xr-x 1 nagata staff 1926112 9 11 21:57 hpdf.dll
日本語 PDF を作成するには、Lua の文字列を Shift-JIS (CP932 = Microsoft Code Page 932) に変換する必要がある。libHaru は日本語エンコーディングとして CP932 か EUC しか対応してないためである(libharu:Encodings)。この件は後日。