pdfmakeでカスタムフォントを使用したPDFファイル生成

# やりたいこと
pdfmakeでカスタムフォントを使用したPDF生成を行う
# pdfmakeとは

> Client/server side PDF printing in pure JavaScript

JavaScriptでクライアント側、サーバ側でのPDF生成ができるモジュールと理解しています。

# 実行環境
* Windows10 Pro 64bit

# 利用する際に必要なツール
1. [Git](https://git-scm.com/)
    * v2.19.0 を利用しています
2. [nodist](https://github.com/nullivex/nodist/releases)
    * v0.8.8 を利用しています
    * `nodist` はWindows環境で `Node.js` を利用するためにインストールしています

# クライアント側でPDF作成できるかチェック
## pdfmakeモジュールを取得

1. 作成した作業ディレクトリにエクスプローラでアクセス
    * 今回は `D:\pdfmakeTest` を作業フォルダとします
2. パス表示部分をクリックし `cmd` と入力
    * 現在のディレクトリをカレントにしたコマンドプロンプトが立ち上がります
3. `git clone https://github.com/bpampuch/pdfmake.git` でモジュールを取得
    * モジュール取得が完了すると、作業フォルダ直下に `pdfmake` というフォルダが生成されます

## pdfmakeモジュールの動作確認
作業フォルダにテスト表示用のJSファイル、HTMLファイルを作成してPDFが出力されるか確認します。
([クライアントのJavaScriptだけでPDF作成（２）](http://kougeisya.biz/programming/389/)を参考にさせていただき、確認環境を作成しました)
作業フォルダの構造は以下です。

```
pdfmakeTest
 L pdfmake            <- 上記でダウンロードした pdfmake のモジュールディレクトリ
 L pdfmakeTest_01.js  <- pdfmake のメソッド呼び出し用JSファイル
 L check_01.html      <- pdfmake 確認用HTMLファイル
```

### ソースコード
#### pdfmakeTest_01.js
```js
// 連想配列で content にPDF出力用のデータを設定
var pdfContent = {content: "This is pdfmake test. これはpdfmakeのテストです。"};

// pdfmakeで content を設定した変数を引数としてPDF生成
pdfMake.createPdf(pdfContent).open();
```

#### check_01.html
```html
<!DOCTYPE html>
<html lang="ja">

  <!-- ヘッダー -->
  <head>
    
    <title>pdfmakeTest</title>
    
    <!-- ↓↓↓ pdfmake用JSファイル呼び出し ↓↓↓ -->

    <!-- pdfmakeを利用するJSファイル(モジュールのBuildフォルダ内のJSファイル) -->
    <script type="text/javascript" src="./pdfmake/build/pdfmake.min.js"></script>
    <!-- pdf生成に利用するフォントJSファイル(モジュールのBuildフォルダ内のJSファイル) -->
    <script type="text/javascript" src="./pdfmake/build/vfs_fonts.js"></script>
    
    <!-- ↑↑↑ pdfmake用JSファイル呼び出し ↑↑↑ -->

    <!-- pdfmake 呼び出し用JSファイル -->
    <script type="text/javascript" src="./pdfmakeTest_01.js"></script>
    
  </head>
  
  <body>
    <!-- 何も書かない -->
  </body>
</html>
```

## PDF生成確認
ブラウザに `GoogleChrome` を利用して動作を確認します。
※ 生成結果はポップアップで表示されますので、ポップアップブロックを許可してください

↓ PDFが生成されることは確認しましたが、日本語はフォントを変えないと表示されないようです。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/146452/bc842624-60c4-1f98-a8e9-66892c7f99de.png)
 
# pdfmakeで利用するフォントの変更
`pdfmake`で日本語が表示できるようにフォントのJSファイル(`vfs_fonts.js`)を更新します。
## フォントの入手
環境を問わず、日本語を表示できる[IPAフォント](https://ja.osdn.net/projects/ipafonts/)を利用させていただきます。
> IPAフォントは、誰でも無償で利用できる、高品位を目指した日本語フォントです。OSI認定の“IPAフォントライセンス”と、フォントのデファクトスタンダードであるOpenTypeフォントフォーマットを採用することで、プラットフォームの種類を問わず、多様な情報機器で共通に利用することができ、どの環境の下でも同じ形状の高品質な文字の表示・印刷を可能にします。本プロジェクトでは、IPAフォントの品質向上を図るとともに、各プラットフォームでの日本語文字表示に関する情報交換の場となることを目指しています。

1. 公式サイトの[IPA Fonts/IPAex Fonts 4書体パック_IPAフォント（Ver.003.03）](https://ja.osdn.net/projects/ipafonts/releases/51868)からフォントファイルをダウンロード
2. zipファイルを展開
    * `ipagp.tff`(等幅ゴシック), `ipam.tff`(等幅明朝) のファイルを利用します

## フォント情報の更新
[CUSTOM FONTS (CLIENT-SIDE)](https://pdfmake.github.io/docs/fonts/custom-fonts-client-side/)を参考にフォント情報を更新します。
### フォントファイルの入れ替え
`pdfmakeTest\pdfmake\examples\fonts`ディレクトリ内のファイル(`Roboto-xxx.ttf`の4ファイル、`sampleimage.jpg`)を削除し、IPAフォントファイル(`ipagp.ttf`, `ipamp.ttf`)を格納します。
### vfs_fonts.js の更新
以下の手順でフォント情報を更新します。

1.  `pdfmake`ディレクトリに移動し、Node.jsモジュールを更新
    * `npm install` (ズラズラっとメッセージが出て更新が行われます)
2. 上記でインストールした`pdfmake\node_modules`の`gulp`を利用した`vfs_fonts.js`の更新
    * `pdfmakeTest\pdfmake\node_modules\.bin\gulp.cmd buildFonts` を入力し`vfs_fonts.js`を更新します
3. フォント情報を`pdfmake`に反映
    * `pdfmake`のフォルダで`npm run build`を行い、モジュールをビルドしなおします

### vfs_fonts.js の確認
テキストエディタでファイルを確認し、`ipagp.ttf`という記述があるかを確認します。
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/146452/be9dcf8d-c5d3-9c0a-1eb8-fc0c64d4b368.png)

# カスタムフォントが正常に利用できるかチェック
## 利用フォントを設定したJSファイルの作成
作業フォルダのテスト表示用のJSファイル、HTMLファイルを更新し、日本語のPDFが出力されるか確認します。
([クライアントのJavaScriptだけでPDF作成（６－日本語フォントテスト）](http://kougeisya.biz/programming/528/)を参考にさせていただき、確認環境を作成しました)
作業フォルダの構造は以下です。

```
pdfmakeTest
 L pdfmake            <- 上記でダウンロードした pdfmake のモジュールディレクトリ
 L pdfmakeTest_02.js  <- pdfmake のメソッド呼び出し用JSファイル
 L check_02.html      <- pdfmake 確認用HTMLファイル
```

## ソースコード
### pdfmakeTest_02.js
先ほど更新したフォントを利用フォントとして設定し、表示する文字列に対して利用フォントを設定しています。

```js
// フォント情報として、ゴシックと明朝を定義
pdfMake.fonts = {
    IPAgothic: {
        normal:      'ipagp.ttf',
        bold:        'ipagp.ttf',
        italics:     'ipagp.ttf',
        bolditalics: 'ipagp.ttf'
   },
    IPAmincho: {
        normal:      'ipamp.ttf',
        bold:        'ipamp.ttf',
        italics:     'ipamp.ttf',
        bolditalics: 'ipamp.ttf'
   }
}

// JSON形式で content にPDF出力用のデータを設定
var pdfContent = {
    content: [
        { text: "This is pdfmake test."},
        { text: "これは等幅ゴシック体(ipagp.tff)のテストです。", font: "IPAmincho"},
        { text: "これは等幅明朝体(ipamp.tff)のテストです。", font: "IPAgothic"}
   ],
   // デフォルトフォントを等幅ゴシック体に変更
   defaultStyle: {
       font: "IPAgothic"
   }
}

// pdfmakeで content を設定した変数を引数としてPDF生成
pdfMake.createPdf(pdfContent).open();
```

### check_02.html
呼び出すJSファイルを変更しただけです。

```html
<!DOCTYPE html>
<html lang="ja">

  <!-- ヘッダー -->
  <head>
    
    <title>pdfmakeTest</title>
    
    <!-- ↓↓↓ pdfmake用JSファイル呼び出し ↓↓↓ -->

    <!-- pdfmakeを利用するJSファイル(モジュールのBuildフォルダ内のJSファイル) -->
    <script type="text/javascript" src="./pdfmake/build/pdfmake.min.js"></script>
    <!-- pdf生成に利用するフォントJSファイル(モジュールのBuildフォルダ内のJSファイル) -->
    <script type="text/javascript" src="./pdfmake/build/vfs_fonts.js"></script>
    
    <!-- ↑↑↑ pdfmake用JSファイル呼び出し ↑↑↑ -->

    <!-- pdfmake 呼び出し用JSファイル -->
    <script type="text/javascript" src="./pdfmakeTest_02.js"></script>
    
  </head>
  
  <body>
    <!-- 何も書かない -->
  </body>
</html>
```

## 日本語が表示されているか確認
できました！
![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/146452/b4f630c5-b0dd-338c-0ac4-93c89c1af29d.png)

# ハマったところ
## カスタムフォント定義ファイルの更新
### 問題
`grunt` を利用してカスタムフォント更新する方法がわかりませんでした。
### 解決
pdfmakeのイシュー([Grunt #794](https://github.com/bpampuch/pdfmake/issues/794))を確認し、`gulp`を利用することに気づきました！
(というよりも、公式のドキュメントには`gulp`が記載されているので、最初にそれを見れば解決していました……。)

## vfs_fonts.js ファイルの内容を pdfmake に反映させる
### 問題
`vfs_fonts.js`を更新しただけでは、`Uncaught File 'ipagp.ttf' not found in virtual file system` というエラーが発生し、フォント情報が `pdfmake.min.js` から読めないようでした。
### 解決
`npm run build` で再度ビルドを行うことで、モジュール設定の更新が行われ、正常に表示することができました！

# 参考サイト
## pdfmake
[bpampuch/pdfmake](https://github.com/bpampuch/pdfmake)
[Grunt #794](https://github.com/bpampuch/pdfmake/issues/794)
[PDFMAKE](https://pdfmake.github.io/docs/)


## カスタムフォント
[クライアントのJavaScriptだけでPDF作成（２）](http://kougeisya.biz/programming/389/)
[クライアントのJavaScriptだけでPDF作成（５－フォント作成）](http://kougeisya.biz/programming/469/)
[クライアントのJavaScriptだけでPDF作成（６－日本語フォントテスト）](http://kougeisya.biz/programming/528/)