ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

FPDFとjapanese.phpでUTF-8の文字を出力するには?

2010-08-27 14:21:37 | PHP

 まえに、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つきにすると、エラーになる)




うんなかんじで、うまくできるとおもう

この記事についてブログを書く
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 次の流行はMapReduceの雛形と... | トップ | Visual Studio 2010におけるS... »
最新の画像もっと見る

PHP」カテゴリの最新記事