PDF Writerを使って開発を進めていたのですが、1ページのオブジェクト量が多くなると、生成に非常に時間がかかる事が分かりました。
改ページすると超速いのですが、オブジェクトを追加していくとどんどん遅くなります。
コードを追ってみると、不要と思われる処理、適切で無いと思われる処理がありましたので修正したところ、20倍ぐらい(体感)速くなりましたのでメモとして上げます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
!
|
-
!
|
-
!
|
|
|
|
|
|
|
!
|
-
|
!
|
-
|
|
|
|
|
|
|
|
|
-
!
|
-
| Index: EnclosedContent.java
===================================================================
--- EnclosedContent.java (revision 17)
+++ EnclosedContent.java (working copy)
@@ -48,6 +48,10 @@
return mContent.toString();
}
+ public int getContentLength() {
+ return mContent.length();
+ }
+
public void addContent(String Value) {
mContent.append(Value);
}
Index: IndirectObject.java
===================================================================
--- IndirectObject.java (revision 17)
+++ IndirectObject.java (working copy)
@@ -92,10 +92,17 @@
return mStreamContent.getContent();
}
+ public int getStreamContentLength() {
+ return mStreamContent.getContentLength();
+ }
+
protected String render() {
StringBuilder sb = new StringBuilder();
sb.append(mID.toPDFString());
Index: Page.java
===================================================================
--- Page.java (revision 21)
+++ Page.java (working copy)
@@ -97,9 +97,11 @@
private void addContent(String content) {
mPageContents.addStreamContent(content);
- String streamContent = mPageContents.getStreamContent();
- mPageContents.setDictionaryContent(" /Length " + Integer.toString(streamContent.length()) + "\n");
- mPageContents.setStreamContent(streamContent);
+++ mPageContents.setDictionaryContent(" /Length " + Integer.toString(mPageContents.getStreamContentLength()) + "\n");
++ }
public void addRawContent(String rawContent) {
|
元凶の1つ目は41行目。この中で長大なStringBuilderをtoString()しており、そのたびに(実際は数回に1度)GCが走ってパフォーマンスが落ちています。
ここで欲しいのは長さだけなので、getStreamContentLength()という関数を作ります。
getStreamContentLength()の中身はその上の9〜11、25〜27行目の通り。
元凶の2つ目は43行目のsetStreamContent()。40行目で作ったStringBuilderを、何故か再度newして作り直しています。というわけでコメントアウト。
なんだかこれで良いのか若干不安ですが、私の利用範囲では動いているのでよしとします。
ご利用はあくまで自己責任で(^^;。
androidでPDFファイルを作成するためにぐぐったところ、PDFWriterが良いという事がわかりました。ただ、日本語に対応していません。
とりあえずダウンロードしてソースを確認すると、意外とシンプルです。
サンプルのデモも付いており、動作を確認してみると、テキストが出力されるようになっています。
ん? PDFなのにテキスト?
と思っていろいろ調べてみると、どうやらPDFファイルというのはテキストで記述できることが分かりました。(超わかりやすい参考文献)
それらを参考に、日本語フォント指定をできるようにしてみました。
ただし、かなりなんちゃってなので、以下の制限があります。
- フォントは埋め込まない(方法が分からなかった)
- フォント幅も結構適当(埋め込まないと等幅になるらしい)
- エンコードはSJIS(90ms-RKSJ-H)固定(Unicodeにトライしたけど何故かうまくいかなかった)
- androidの標準(のはずの)Droid Sans Japaneseが指定できない(トライしたけど何故か表示されなかった)
一応以下のフォント指定が可能ですが、PDFファイル内の属性として指定可能なだけで、フォント幅はすべて一定です。
フォント名 | 指定文字列 |
MSゴシック | MS_GOTHIC |
MS明朝 | MS_MINCHO |
MSPゴシック | MSP_GOTHIC |
MSP明朝 | MSP_MINCHO |
メイリオ | MEIRYO |
使用例:
1
2
3
4
5
6
7
| -
!
-
!
-
!
| PDFWriter mPDFWriter = new PDFWriter(PaperSize.A4_HEIGHT, PaperSize.A4_WIDTH);
mPDFWriter.setFont(JapaneseFonts.MEIRYO);
mPDFWriter.addTextAsHex(X, Y, fontSize, JapaneseFonts.stringToSjisHex("abcihjk全角もじれつ"));
:
|
出力例:
_ 必要なもの
- apwlibraryをダウンロード
- 以下のファイルを追加・置き換える
以上です。フォントファイルを埋め込もうと頑張りましたが挫折しました。PDFのフォーマット難しい・・・。
なお、apwlibraryはBSDライセンスです。(上記ソースもBSDライセンスです)
参考文献:
手書きPDF入門 - http://www.kobu.com/docs/pdf/pdfxhand.htm
Portable document format(Adobe) - http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf