■PDFファイルを生成する方法
まずはPDFファイルを生成する方法を知らなければ話になりません。ということで、調査しました。
- 一からライブラリを自作する
jspdf(http://code.google.com/p/jspdf/)などという漢気あふれるライブラリがあるのですから、やってやれないことはない!と思い、さっそくPDFの仕様書(http://www.adobe.com/devnet/pdf/)をAdobe社からダウンロードしてきたのですが、31MB, 500ページ以上あります。なにこれこわい。 - Adobe PDF Library(http://www.adobe.com/devnet/pdf/library/ http://www.est.co.jp/pdfl/index.html)
本家のライブラリです。日本ではイースト社がライセンスしてるみたいですが、どう見ても有償です。チェンジお願いします。 - libHaru(http://libharu.org/wiki/Main_Page)
こうして散々探した挙句ついに見つけた至高のPDFライブラリがこちら。C言語で書かれており、iPhoneでもバッチリ動きそうです!もちろんオープンソース!素晴らしい!
■libHaruをXcodeでビルドする
1.libHaruのソースコードをダウンロードしてXcodeプロジェクトに追加
最新のソースコードをhttp://libharu.org/wiki/Downloadsからダウンロードしてきて解凍します。このまま自分のMacで使えるようにするだけなら. configureしてmakeしてmake installすれば一発なのですが、あいにくそれではiPhoneで動かすことが出来ません。
includeディレクトリにヘッダファイルが、srcディレクトリにCソースコードが入ってますので、これら全部を自分のXcodeプロジェクトにコピーして取りこみます。
2.libpngのソースコードをダウンロードしてXcodeプロジェクトに追加
libHaruを用いてPDFに画像を出力したいときには、別途libpngが必要になります。そこで、libpngも一緒にビルドすることにします。libpngのソースコードはhttp://www.libpng.org/pub/png/libpng.htmlから入手できますので、これをダウンロードしてきてXcodeに追加してビルドすればよいのですが、ここではもっと簡単で確実に動く方法をご紹介します。そう、「既にlibpngをビルドして使っている他のiPhoneプロジェクトからパクる」です!(もちろん、きちんとライセンスに違反していないことを確認しましょう)
おあつらえ向きなことに、cocos2d for iPhoneの0.8.1以降(http://code.google.com/p/cocos2d-iphone/source/browse/#svn/trunk)では内部的にlibpngを使用しています。これを真似しない手はありません。さっそくcocos2d for iPhoneの最新ソースを取得し、Xcodeでプロジェクトを開いて、Support/external/libpng以下のソースをコピーして自分のプロジェクトに追加しましょう。
3.libHaruをconfigureする
. configureで動けばいいのですが、多分. configureしても今の自分のMacの環境に合わせてConfigureされてしまい、iPhoneでは動かないだろうと思ったので、自分の手でconfigureすることにしました。といっても、直すのは一箇所だけです。includeディレクトリに入っていた
hpdf_config.h.in
ファイルを以下のように修正します。/* include/hpdf_config.h.in. Generated from configure.in by autoheader. */書き換えたら、ファイル名を
/* Define to 1 if you have theheader file. */
#undef HAVE_DLFCN_H
#define HAVE_DLFCN_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_INTTYPES_H
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `png' library (-lpng). */
#undef HAVE_LIBPNG
#define HAVE_LIBPNG 1
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
#define HAVE_LIBZ 1
/* Define to 1 if you have theheader file. */
#undef HAVE_MEMORY_H
#define HAVE_MEMORY_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_STDINT_H
#define HAVE_STDINT_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_STDLIB_H
#define HAVE_STDLIB_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_STRINGS_H
#define HAVE_STRINGS_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_STRING_H
#define HAVE_STRING_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_SYS_STAT_H
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_SYS_TYPES_H
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have theheader file. */
#undef HAVE_UNISTD_H
#define HAVE_UNISTD_H 1
/* debug build */
#undef HPDF_DEBUG
#ifdef DEBUG
#define HPDF_DEBUG 1
#endif
/* debug trace enabled */
#undef HPDF_DEBUG_TRACE
#ifdef DEBUG
#define HPDF_DEBUG_TRACE 1
#endif
/* libpng is not available */
#undef HPDF_NOPNGLIB
/* zlib is not available */
#undef HPDF_NOZLIB
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
#define STDC_HEADERS 1
/* Define to `unsigned int' ifdoes not define. */
/* #undef size_t */
hpdf_config.h
に変更します。4.Xcodeから新規ビルドターゲットを作成する
ソースコードの準備が出来たら、次はソースコードをビルドしてlibharu.aとlibpng.aを生成するためのビルドターゲットを新規に作成します。ビルドターゲットは使い方を覚えると非常に便利です。
最初にlibpngのビルドターゲットを作ります。libpngのビルドターゲットは、2.でご紹介したとおりcocos2d for iPhoneの最新ソースのXcodeプロジェクト内に既に用意されていますので、これを真似して作るとよいです。ただし、libpngをビルドする際にzlib.dylibが必要になりますので、自分のプロジェクトにzlib.dylibを追加するようにしておいてください。最初からiPhone SDKの一部として用意されています。
続いてlibHaruのビルドターゲットを作成します。こんな感じです。
最後に、libharu.aを自分のiPhoneプロジェクトの依存ライブラリに追加します。
5.レッツコンバイン!
これでビルドする準備が整いましたので、いよいよビルドします。
緊張の一瞬!Cmd+Bをプログラムドライブ!!
できました!!!!
■Hello, libHaru!
無事にビルドが完了いたしましたので、次はいよいよPDFを生成してファイルに出力してみます。
// TEST CODE: testing libharu
NSString *path = nil;
const char *pathCString = NULL;
NSLog(@"[libharu] PDF Creation START");
HPDF_Doc pdf = HPDF_New(NULL, NULL);
NSLog(@"[libharu] Adding page 1");
HPDF_Page page1 = HPDF_AddPage(pdf);
NSLog(@"[libharu] SetSize page 1");
HPDF_Page_SetSize(page1, HPDF_PAGE_SIZE_A4, HPDF_PAGE_LANDSCAPE);
NSLog(@"[libharu] TextOut page 1");
HPDF_Page_BeginText(page1);
HPDF_UseJPFonts (pdf);
HPDF_UseJPEncodings (pdf);
HPDF_Font fontEn = HPDF_GetFont(pdf, "Helvetica", "StandardEncoding");
HPDF_Font fontJp = HPDF_GetFont(pdf, "MS-Mincyo", "90ms-RKSJ-H");
HPDF_Page_SetFontAndSize(page1, fontEn, 16.0);
HPDF_Page_TextOut(page1, 100.00, 100.00, "Hello libHaru!");
HPDF_Page_SetFontAndSize(page1, fontJp, 16.0);
HPDF_Page_TextOut(page1, 100.00, 60.00, [@"はろー日本語" cStringUsingEncoding:NSShiftJISStringEncoding]);
HPDF_Page_EndText(page1);
NSLog(@"[libharu] Path drawing page 1");
HPDF_Page_SetLineWidth(page1, 4.0);
HPDF_Page_SetRGBStroke(page1, 1.0, 0, 0);
HPDF_Page_Rectangle(page1, 200, 200, 40, 150);
HPDF_Page_Stroke(page1);
NSLog(@"[libharu] PNG image drawing page 1");
path = [[NSBundle mainBundle] pathForResource:@"portrait2"
ofType:@"png"];
pathCString = [path cStringUsingEncoding:NSASCIIStringEncoding];
NSLog(@"[libharu] LoadPngImageFromFile path:%@\n pathCString:%s", path, pathCString);
HPDF_Image image = HPDF_LoadPngImageFromFile(pdf, pathCString);
HPDF_Page_DrawImage(page1, image, 300, 50, 245, 319);
// Get documents directory
NSArray *arrayPaths =
NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
YES);
path = [arrayPaths objectAtIndex:0];
path = [path stringByAppendingPathComponent:@"test.pdf"];
pathCString = [path cStringUsingEncoding:1];
NSLog(@"[libharu] SaveToFile path:%@\n pathCString:%s", path, pathCString);
HPDF_SaveToFile(pdf, pathCString);
NSLog(@"[libharu] Freeing PDF object ");
HPDF_Free(pdf);
NSLog(@"[libharu] PDF Creation END");
これを実行すると、アプリのDocumentディレクトリにtest.pdfが生成されるはずです。
■実機で試してみる
シミュレータでは動くようになりましたが、実機で動かなければ何の意味もありません。ということで、いよいよ実機でテストしてみます!生成したPDFファイルを表示するためのUIWebViewを作成し、実機で表示してみた結果がこちら。
Hooray!!
■さて次は
いよいよ次からが本番、UIViewの中身をPDFに変換して出力する機能を作ってみようと思います!