SHIFT_JISに無い文字をFPDFで表示する :【PHP】

文字列中の HTML 用「数値文字参照」文字列( &#数値; ) の変換
このサンプルでは、元のソースコードが UTF-8 なので、変換が成功しますが
EUC-JP や SHIFT_JIS では変換できないので正しく表示されません。
つまり、&#数値; 表現のままであれば、全てのキャラクタセットで
文字列が正しく表示されるという事です。
( ※ DBとしてデータを正しく登録したい場合以外は変換する必要は無いという結論 )

ここで重要なのは、$b が正しい unicode 文字列 であるテストがされた
という事で、これを使って、FPDF の japanese.php を少し変更して
SHIFT_JIS ベースのソースから SHIFT_JIS に無い文字を出力する事ができます。

こちら では、画像を使ってその実現をしていますが、これを書いた
時は、まだ PDF の仕様について調査していなかったので、
簡単に unicode で渡せる事を知らなかったからです。
<? header( "Content-Type: text/html; Charset=utf-8" ); ?>

<STYLE type="text/css">
* {
	font-size:22px;
}
</STYLE>

<?
mb_language( "ja" );
mb_internal_encoding("EUC-JP");

// ***********************************************
// 変換用のコールバック関数
// ***********************************************
function rep_func($matches)
{
	$a = $matches[1]+0;
	$b = chr(($a-($a%256))/256).chr($a%256);
	$c = mb_convert_encoding( $b, "utf-8", "unicode" );

	return( $c );
}

$target = "文字列中に<b>(&#8531;)</b>含まれた &#数値;
	 を実コード(<b>&#40767;</b>)に変換する";

$a = preg_replace_callback(
	"/&#(\d+);/",
	rep_func,
	$target
);

print $a;

print "<br>";

print $target;
?>
EUC 用と unicode 用のフォント追加関数(AddSJISFontは、こちらを参照)
二つ追加しています。それぞれ EUC-HUniJIS-UTF16-H を使用していますが、
これは PDF の仕様にある以下の表にあったものを使用しています。

最初、UniJIS.UCS2.H を使用してテストしていると、SHIFT_JISに無い文字
を殆ど表示できない事が解り、UniJIS.UTF16-H に変更しました。
Predefined CJK CMap
83pv.RKSJ.HMac OS, JIS X 0208 character set
with KanjiTalk6 extensions, Shift-JIS encoding, Script Manager code 1
90ms.RKSJ.HMicrosoft Code Page 932 (lfCharSet 0x80),
JIS X 0208 character set with NEC and IBMRextensions
90ms.RKSJ.VVertical version of 90ms.RKSJ.H
90msp.RKSJ.HSame as 90ms.RKSJ.H but replaces half-width
Latin characters with proportional forms
90msp.RKSJ.VVertical version of 90msp.RKSJ.H
90pv.RKSJ.HMac OS, JIS X 0208 character set with KanjiTalk7
extensions, Shift-JIS encoding, Script Manager code 1
Add.RKSJ.HJIS X 0208 character set with Fujitsu
FMR extensions, Shift-JIS encoding
Add.RKSJ.VVertical version of Add.RKSJ.H
EUC.HJIS X 0208 character set, EUC-JP encoding
EUC.VVertical version of EUC.H
Ext.RKSJ.HJIS C 6226 (JIS78) character set with
NEC extensions, Shift-JIS encoding
Ext.RKSJ.VVertical version of Ext.RKSJ.H
HJIS X 0208 character set, ISO-2022-JP encoding
VVertical version of H
UniJIS.UCS2.HUnicode (UCS-2) encoding for the Adobe-Japan1 character
collection
UniJIS.UCS2.VVertical version of UniJIS.UCS2.H
UniJIS.UCS2.HW.HSame as UniJIS.UCS2.H but replaces proportional
Latin characters with half-width forms
UniJIS.UCS2.HW.VVertical version of UniJIS.UCS2.HW.H
UniJIS.UTF16-HUnicode (UTF-16BE) encoding for the Adobe-Japan1
character collection; contains mappings for all characters in the JIS X 0213:1000 character set
UniJIS.UTF16-VVertical version of UniJIS.UTF16-H NAME
DESCRIPTION
function AddSJISFont($font='MS-Mincho',$family='SJIS')
{
	//Add SJIS font with proportional Latin
	$name=$font;
	$cw=$GLOBALS['SJIS_widths'];
	$CMap='90msp-RKSJ-H';
	$registry=array('ordering'=>'Japan1','supplement'=>2);
	$this->AddCIDFonts($family,$name,$cw,$CMap,$registry);
}

function AddUJISFont($font='MS-Mincho',$family='UJIS')
{
	//Add SJIS font with proportional Latin
	$name=$font;
	$cw=$GLOBALS['SJIS_widths'];
	$CMap='EUC-H';
	$registry=array('ordering'=>'Japan1','supplement'=>2);
	$this->AddCIDFonts($family,$name,$cw,$CMap,$registry);
}

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);
}
SHIFT_JIS 環境における、&#数値; 文字混在データを FPDF に渡す実装
SHIFT_JIS 部分は単純に UNICODE に変換すればいいのですが、&#数値; 部分は
自分でデコードするので最初にテストした、preg_replace_callback を利用して
完全コンバートします
// フォント追加
$this->AddUniJISFont();
// フォント選択
$this->SetFont( 'UniJIS', '', 16 );
// 入力値をコンバートして出力
// ※ SHIFT_JIS で 「あ&#8531;い&#40767;う」 のようなデータが対象
$this->LocText( 40, 23, ConvUniJIS($_GET['text']) );

function rep_func($matches)
{
	$a = $matches[1]+0;
	$b = chr(($a-($a%256))/256).chr($a%256);

	$GLOBALS['uni_parts'][]	= $b;

	return( chr(1) );
}

function ConvUniJIS($text) {

	$GLOBALS['uni_parts'] = array();

	$ret =preg_replace_callback(
		"/&#(\d+);/",
		rep_func,
		$text
	);

	$ar = explode(chr(1),$ret);

	$result = "";
	for( $i = 0; $i < count( $ar ); $i++ ) {
		if ( $ar[$i] != '' ) {
			$result .= 
				mb_convert_encoding( $ar[$i], "unicode", "shift_jis" );
		}
		if ( count( $ar ) > 0 ) {
			if ( $i < count( $GLOBALS['uni_parts'] ) ){
				$result .= $GLOBALS['uni_parts'][$i];
			}
		}
	}

	return $result;

}
で、何故か 蕙 の文字が PDF に出力できないです。
Microsoft では表示されるので、単純に考えるとAdobe のバグですが、
GD でもダメだったので、ひょっとすると Microsoft 側かもしれないです。