iTextを用いたJavaによるPDFファイル出力


## 目的
* ソースコードの文字を座標を指定して描画する
* それぞれの文字がどの座標に存在するかを確認できるようにする

## 利用するツール
* iText : JavaでPDFファイルを出力するライブラリ
* PDFBox : PDF文書から文字とその文字のページ上の出現位置を取り出すために利用

## 手順
1. iTextのインストールと利用方法の確認
2. PDFBoxのインストールと利用方法の確認
2. ソースコードの提示方法の設定
3. 1件のコードにたいして実装
4. N件のコード用に処理を自動化

## 1. iTextのインストール
### Gradleで依存関係を処理する
* ここでGradleの書き方を調べる：https://mvnrepository.com/
* 作成したGradle projectの依存関係に以下を追加

```
// https://mvnrepository.com/artifact/com.itextpdf/itextpdf
compile group: 'com.itextpdf', name: 'itextpdf', version: '5.0.6'
```

### Error 1

```
Exception in thread "main" com.itextpdf.text.DocumentException: Font 'KozMinPro-Regular' with 'UniJIS-UCS2-H' is not recognized.
	at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:699)
	at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:606)
	at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:441)
	at iText.IndexAction.createPdf(IndexAction.java:29)
	at iText.Main.main(Main.java:12)
```

* 原因 : 'KozMinPro-Regular'が認識できていないこと
* 解決法 : 使用するFontを以下のように変更

```
BaseFont bf1 = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
```

### iTextのページサイズの指定は"pt"を利用する

* 1mm = 2.83pt
* 1pt = 0.35mm
* したがって，横幅を350mmにしたければ, 350[mm] * 2.83[pt/mm] = 992.1275 に設定

```
// define page size as 35x25cm
// iText use "pt" thus we need to transform "mm" to "pt"
// with multiplying "2.83465"
float PAGESIZE_X = (float) (350 * 2.83465);
float PAGESIZE_Y = (float) (250 * 2.83465);
```

## 2. PDFBoxのインストールと利用方法の確認
### Gradleで依存関係を処理する
* 作成したGradle projectの依存関係に以下を追加
* 参考にしている記事と同じv1.8.0を利用する

```
// https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '1.8.0'
```

### PDFのテキストの座標を取得する
* テキスト抽出にはPDFBoxのExtractTextを利用する
* ExtractTextクラスではpdfbox.util.PDFTextStripperを呼び出して，実際にPDF文書からテキストを取り出している．したがって，PDFTextStripperのサブクラスを作成し、processTextPositionメソッドをoverrideすることで追加情報（文字列の座標）を取得する.
* 参考：PDF文書から文字とその文字のページ上の出現位置を取り出す (http://www.my-notebook.net/8fd35020-e079-4856-b9bd-d4d5af86d885.html)

```
@Override
  protected void processTextPosition(TextPosition text) {
    StringBuffer sb = new StringBuffer();
    super.processTextPosition(text);

    sb.append(text.getCharacter()).append(",");
    // sb.append("pageIndex=" + pageIndex).append(",");

    sb.append("x=" + text.getX()).append(",");
    sb.append("y=" + text.getY()).append(",");
    sb.append("width=" + text.getWidth()).append(",");
    sb.append("height=" + text.getHeight());

    printWriter.println(sb.toString());
  }
```

## 3. ソースコードの提示形式の設定
### 提示形式は以下のとおり
* 描画領域のサイズ：35x25 cm
* 文字色：白
* 文字サイズ：0.8x0.8 cm
* 行間 : デフォルト
* 背景色 : マイルドな黒 #7f7f7f

## 4. 1件のコードにたいして実装
* ERROR : tab文字を読み込まない
* 対処 : tabを空白に変換する

## ソースコードの行数に応じて上下のマージンを調整する
### コードブロックはParagraphとして格納している
* 参考：http://tutorials.jenkov.com/java-itext/paragraph.html

### BaseFontを使って文字のAscent, Decentを計算できる
以下のコードによってフォントのHeightを計算できる．
ascentは正の値，descentは負の値で返されるので，両者の差を取るとフォントのHeightになる．

```
float ascent = bf.getAscentPoint(text, FONTSIZE);
float descent = bf.getDescentPoint(text, FONTSIZE);
float height = ascent - descent;
```

* 参考："How to calculate the height of an element?" http://developers.itextpdf.com/ja/node/3132

![LwZJF.png](https://qiita-image-store.s3.amazonaws.com/0/70731/fe150f21-df7a-abc6-2adf-f9d5c4c29d01.png "LwZJF.png")

## PsychoPyで利用するためにPDFをJPEG画像化する
* 参考: http://inforati.jp/apple/mac-tips-techniques/multimedia-hints/how-to-change-a-image-format-with-mac-preview-app.html

## その他
### Eclipseのformatterをgoogle style guideに変更
1行の折り返し文字数が気に入らないので，google のものに変更

手順

* google style guideのrepositoryをcloneしてくる(https://github.com/google/styleguide)
* Eclipseの環境設定で"formatter"と検索して出てきた窓からcloneしたファイルをインポート
* 参考：http://sgrit.hatenablog.com/entry/2014/11/24/015715

### EclipseのKeybindをEmacsに変更

* 参考 : http://qiita.com/scnsh/items/aa304b9433e353333622

### 空白文字列のCheckにはApache Commons LangのStringUtilsクラスが便利。
* 参考：http://arison.jp/blog/2013/02/06/java-stringutils-null-space-check/
* 以下をGradle buildに追加して利用する

```
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'
```


## 参考文献
* JavaでPDFファイルを出力する(iTextライブラリ)【準備編】(http://d.hatena.ne.jp/MoonMtLab/20130913/1379021689)
* JavaでPDFファイルを出力する(iTextライブラリ)【出力編】(http://d.hatena.ne.jp/MoonMtLab/20130914/1379114572)
* PDFBox ( https://pdfbox.apache.org/ )
* PDF文書から文字とその文字のページ上の出現位置を取り出す (http://www.my-notebook.net/8fd35020-e079-4856-b9bd-d4d5af86d885.html)