PDFlib での文字列の扱い
PDFlib で扱う文字列は3種類に分類でき、Unicode 対応ではない言語バインディングではこれらを意識する必要があります。ここでは、PDFlib での文字列の扱いについて説明します。
なお、PDFlib 9 で導入された stringformat により、Unicode 対応ではない場合でも文字列の扱いが簡単になりました。また PDFlib 10 より C 言語以外では "stringformat=utf8" がデフォルトになりました。
言語バインディングの Unicode 対応、非対応
PDFlib では、文字列を Unicode で扱う言語バインディングを Unicode 対応と呼んでいます。
PDFlib 10 時点での Unicode 対応のバインディングは以下の通りです。
- C++
- .NET
- Java
- Objective-C
- Python
- RPG
Unicode 対応のバインディングでは、当ページで説明する文字列種別を意識する必要はありません。
一方 Unicode 対応ではない下記の言語バインディングでは、文字列の種類毎に処理が少々複雑になります。
- C
- C++ (PDFlib 7 との互換性のためのレガシーバインディング)
- Perl
- PHP
- Ruby
文字列の種類
PDFlib が PDF に出力する文字列は、以下の3種類に分類できます。
- 内容文字列
- ハイパーテキスト文字列
- 名前文字列
PDFlib がどの文字列として扱うかは、PDFlib API Reference に記載されています。
内容文字列
ページ内容の作成に使われる文字列です。PDF_load_font() の textformat 引数と encoding 引数によって制御されます。encoding を unicode にした場合は文字列を UTF-16 として扱い、それ以外では bytes として扱います。
ハイパーテキスト文字列
しおりや文書情報等のインタラクティブ要素の作成に使われる文字列です。set_option() の hypertextencoding の値によって制御されます。hypertextencoding を unicode にした場合は UTF-16 として扱い、それ以外では bytes として扱います。
名前文字列
文書情報のカスタムプロパティの名前やフォントファイルの名前に使われる文字列です。デフォルトでは host エンコーディングとして扱いますが、文字列の先頭に UTF-8 の BOM (\xEF\xBB\xBF) がある場合は UTF-8 として扱います。また、usehypertextencoding が true の場合、ハイパーテキスト文字列の解釈方法が名前文字列にも適用されます。
bytes として扱う場合、日本語 OS 環境では Shift-JIS を渡すと日本語が表示されます。しかしながら、host のエンコーディングによっては文字化けが発生するため、UTF-16 や UTF-8 等の Unicode の符号化方式を使用することをお勧めします。
PDFlib 9 で導入された stringformat について
PDFlib 9 では、Unicode 非対応バインディング向けの set_option() 関数のキーワードとして stringformat が追加されました。
stringformat の値には "legacy" または "utf8" (iSeries/zSeries では "ebcdicutf8") を設定することができ、"utf8" では上記の内容文字列、ハイパーテキスト文字列、名前文字列のエンコーディンが、すべて UTF-8 になります。これにより、文字列の種類を意識することなく、ソースコードを UTF-8 で保存するか、PDFlib 関数に渡す前に UTF-8 に変換するだけでよくなりました。
Unicode 対応 / 非対応による処理の違い
以下は、Unicode 対応の Java と Unicode 非対応の PHP で、上記の3種類の文字列を持つ PDF を作成する場合のサンプルコードです。
Java では PDFlib が文字列を適切な形へ自動変換するため、プログラマーが気をつけることはありません。PHP では変換を上記の内容文字列、ハイパーテキスト文字列、名前文字列について適切に変換を行う必要があるため、処理が少々複雑になります。(ただし "stringformat=utf8" の場合はすべて UTF-8 になります)
なお、日本語を表示するためには日本語フォントが必要です。下記のサンプルでは MS 明朝 を利用していますが、IPA フォント 等のフォントでも同様です。
import com.pdflib.pdflib;
import com.pdflib.PDFlibException;
public class pdflib_test {
public static void main(String argv[]) {
int font;
pdflib p = null;
// フォントファイルを格納したディレクトリへのパス
String searchpath = "/path/to/resource/fonts";
try {
p = new pdflib();
p.set_option("errorpolicy=return");
p.set_option("searchpath=" + searchpath);
if (p.begin_document("pdflib_test.pdf", "") == -1)
throw new PDFlibException();
p.begin_page_ext(0, 0, "width=a4.width height=a4.height");
p.set_info("Title", "文字列の取り扱い");
p.set_info("カスタムキー", "カスタムバリュー");
p.set_option("FontOutline={MS明朝=msmincho.ttc}");
font = p.load_font("MS明朝:0", "unicode", "");
if (font == -1)
throw new PDFlibException();
p.setfont(font, 24);
p.set_text_pos(50, 700);
p.show("内容文字列");
p.end_page_ext("");
p.end_document("");
}
catch (Exception e) {
System.err.println(e.getMessage());
}
finally {
if (p != null)
p.delete();
}
}
}
Java 1.7 / PDFlib 9
<?
// フォントファイルを格納したディレクトリへのパス
$searchpath = "/path/to/recource/fonts";
$p = 0;
// EUCJP-win から UTF-8 に変換する関数
function convert_UTF8($str) {
return "\xEF\xBB\xBF" . mb_convert_encoding($str, "UTF-8", "EUCJP-win");
}
try {
$p = new pdflib();
$p->set_option("errorpolicy=return");
$p->set_option("searchpath=$searchpath");
// stringformat を utf8 に設定
$p->set_option("stringformat=utf8");
if ($p->begin_document("", "") == 0)
throw new PDFlibException();
$p->begin_page_ext(0, 0, "width=a4.width height=a4.height");
// 第一引数は名前文字列、第二引数はハイパーテキスト文字列 (共に UTF-8)
$p->set_info(convert_UTF8("Title"), convert_UTF8("文字列の取り扱い"));
$p->set_info(convert_UTF8("カスタムキー"), convert_UTF8("カスタムバリュー"));
// option list のエンコードは UTF-8 BOM の有無に従う (この場合 UTF-8)
$p->set_option(convert_UTF8("FontOutline={MS-Mincho=msmincho.ttc}"));
// 第一引数は名前文字列 (UTF-8)
$font = $p->load_font(convert_UTF8("MS明朝:0"), "unicode", "");
if ($font == 0)
throw new PDFlibException();
$p->setfont($font, 24);
$p->set_text_pos(50, 700);
// 内容文字列 (UTF-8)
$p->show(convert_UTF8("内容文字列"));
$p->end_page_ext("");
$p->end_document("");
$buf = $p->get_buffer();
$len = strlen($buf);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: filename=pdflib.pdf");
print $buf;
}
catch (Exception $e) {
echo($e);
}
if ($p != 0) {
$p->delete();
$p = 0;
}
?>
PHP 5 / PDFlib 9 (ソースコードは EUC-JP を想定)