まえに、PHPで、FPDFとjapanese.phpを使ってPDFを出力するってことを書いたけど、
あれだと、UTF-8で出力できない(SHIFT-JISで出力)
そのわけは、japanese.phpで、フォント指定する際、AddSJISFontにおいて、以下のように
function AddSJISFont($family='SJIS') { //Add SJIS font with proportional Latin $name='KozMinPro-Regular-Acro'; $cw=$GLOBALS['SJIS_widths']; $CMap='90msp-RKSJ-H'; $registry=array('ordering'=>'Japan1','supplement'=>2); $this->AddCIDFonts($family,$name,$cw,$CMap,$registry); } |
(上記 < >は、本当は半角)
$CMap='90msp-RKSJ-H';
と指定しているから。
CMapとは、文字コードとフォントの字形の対応をとるマップ(対応表)のことで、
それが、RKSJ、すなわち、ローマンかなSJIS用と指定してある。
なので、SJISになる。
これを、UTF-8用にすると、UTF-8で出力できる(が、実は、・・・この続きはあとで書く)
このRKSJなどについて、詳しくは、
CID-Keyedフォント
http://www.screen.co.jp/ga_product/sento/products/new0.html
にかいてある(「83pv-RKSJのお話」のところ)
なので、出力方法は2とおり。
1つは、UTF-8をSJISに変換して出力
他方は、UTF-8をUnicodeのCMAPを使って出力する。
以下、2とおりについて説明する。
■UTF-8をSJISに変換して出力
この方法は、お手軽にできる。出力時にmb_convert_encodingするだけ。
こんなかんじ。
<?php require('japanese.php'); $pdf=new PDF_Japanese(); $pdf->AddSJISFont(); $pdf->Open(); $pdf->AddPage(); $pdf->SetFont('SJIS','',18); $pdf->Write(8,mb_convert_encoding("かきくけこ","SJIS","UTF-8")); $pdf->Output(); ?> |
(上記 < >は、本当は半角)
ただ、これを保存するとき、UTF-8で保存することになると思うけど、
「BOM付きUTF-8」で保存すると、PDFが出力できない(エラーになる)
「BOMつきUTF-8」は、メモ帳でUTF-8を保存すると、そうなる。
メモ帳では見えないが、ファイルの頭にUTF-8を示す文字が入っていて
(これがBOM。美乳とかとおなじようなもの)
これでUTF-8と判断しやすくなるんだけど、
PDF書き出しの場合、このBOMがファイルの先頭に入って、エラーになってしまう。
そこで、UTF-8書き出しを、BOMなしにする。
TeraPadだと、UTF-8Nにする。
eclipseだと、はじめから、BOMなしで保存するからOK
ただし、欠点として、SJISにない、UTF-8の文字は出力できない。
■UTF-8をUnicodeのCMAPを使って出力する
SJISにない、UTF-8の文字を出力するには、UTF-8のCMapを使えば・・・
となるけど、UTF-8のCMapに対応してないみたいなので(エラーになる)
UTF-16のCMAPを使って出力する。
そのため、修正箇所は2箇所
(1)japanese.phpで、UTF-16のCMap用関数を作成
(2)書き出すときにはUTF-8からUTF-16に変換して出力
この件について、以下のサイトが詳しく書いてある。
SHIFT_JISに無い文字をFPDFで表示する :【PHP】
http://winofsql.jp/sh/html/pdf_unicode1.htm
以下、上記のサイトをもとに、説明する。
(1)japanese.phpで、UTF-16のCMap用関数を作成
japanese.phpに、以下の関数を追加する。
function AddUniJISFont($font='MS-Mincho',$family='UniJIS') { //Add SJIS font with proportional Latin $name=$font; $cw=$GLOBALS['SJIS_widths']; $CMap='UniJIS-UTF16-H'; $registry=array('ordering'=>'Japan1','supplement'=>2); $this->AddCIDFonts($family,$name,$cw,$CMap,$registry); } |
(上記 < >は、本当は半角)
$CMap='UniJIS-UTF16-H';が違うだけ。
'UniJIS-UTF16-H'が、UTF-16のCMap。
(このソースは、上記リンクサイトの丸写しです)。
(2)書き出すときにはUTF-8からUTF-16に変換して出力
そして、書き出すときは、こんなかんじ。
<?php require('japanese.php'); $pdf=new PDF_Japanese(); $pdf->AddUniJISFont(); $pdf->Open(); $pdf->AddPage(); $pdf->SetFont('UniJIS','',18); $pdf->Write(8,mb_convert_encoding("あいうえお","unicode","utf-8")); $pdf->Output(); ?> |
(上記 < >は、本当は半角)
AddUniJISFontを使い、SetFontでUniJISを指定している。
そして、mb_convert_encodingで、unicode(UTF-16)に変換している。
このとき、上記「UTF-8をSJISに変換して出力」でも書いたけど、
このファイルを「BOMなしの」UTF-8で保存すること
(BOMつきにすると、エラーになる)
うんなかんじで、うまくできるとおもう