2006-12-26 [長年日記]

Windows VistaのJIS2004対応 まとめなおし [tech]


とりあえずこのぐらいはね

この話については、Character Set(文字集合)と符号化(Encoding)の違いを意識しておく必要があるだろう。
ピンとこない人は以下のエントリあたりで。

404 Blog Not Found:Unicodeは文字集合か符号化方式か
404 Blog Not Found:備忘録: Unicode, UCS, and UTF
Character Set vs. Encoding

このあたりをちゃんと認識していないと、余計な手間が増えるだけだと思う。


で、どんな環境でテストするのさ

Windowsの次期バージョンWindows Vista(TM)において日本語フォント環境を一新
マイクロソフト,新文字セット「JIS2004」への移行措置を明らかに - ニュース:ITpro

MSゴシックファミリー、MS明朝ファミリーと、Vistaで追加になるメイリオフォントが対象。
"JIS2004に対応した"とここで言っているところのフォントは、あとあと Windows XP に対しても配布されるらしい。(2007/6/19 追記:配布されているなぁ)
ちなみに、

http://www.asahi-net.or.jp/~sd5a-ucd/freefonts/XANO-mincho/index.html.ja.sjis

の様なフォントを使うことでXPでもアプリケーションのテストなどはできる。


(追記 2008/05/19)
メイリオも正式にXP向けに提供された。

ダウンロード詳細 Windows XP 向け ClearType 対応日本語フォント


JIS2004とはいうものの

JIS2004対応とは言っても、JIS X 0213(JIS2004のことね)に記述がある符号化——EUC-JIS-2004, ISO-2022-JP-2004, Shift_JIS-2004——のことは無視して、Unicodeでの符号化だけしかとりあえず考えてない。まぁ、問題ないよな?
Vista のメモ帳(notepad)で保存するときにそれらの符号化が選べるのかどうか、http://q.hatena.ne.jp/1167033462 で質問をした。
あと詳しくは見ていないが、EUCの場合は新しく追加になる文字も今までと同様の考え方で符号化できる……らしい。
文字集合としては、JIS2004の全ての文字はUnicodeでもすでに定義済みである(Unicode3.2で完全に定義されたようだ)。


どんな文字が問題なの?

(1)字形が変更になる文字がある
code point はそのままだが、字形が変わる文字がある。
詳細は以下のpdf。

http://www.jisc.go.jp/newstopics/2005/040220kanjicode.pdf

「JISでは字形は規定していない*1」ので、「パソコンなどに搭載される字形の変更を求めるものではない」が、Vista で搭載されるフォントでは間違いなく字形が変更される。
エンドユーザへの周知が必要である、という点を除けば大きな問題ではないだろう*2
Vista と XPとで、同じデータを同じアプリケーションで見ているのに字が違うとなるわけだ。
そんなケースでは因果が判りやすいのだが、クライアント(例えばブラウザ上で走っているWebアプリケーション)からの要求を受けて、サーバ側の方でプリンタから出力になるケースでは混乱するかも。Webサーバとか、プリンタサーバとかネットワーク機能搭載の複合機とかが間に入ると、エンドユーザには判りにくくなるのではないか。
あと、フォントを埋め込まないPDFがどうなるかも確認が必要?


2007/1/24追記
Vista搭載のフォントでJIS2004での変更以外にも、‖という記号が字形(?)が変化していることを発見。
2007/1/30追記
そんな簡単な話じゃなかった。U+2016(DOUBLE VERTICAL LINE)はそのままの字形だけど("VERTICAL"だからそりゃそうだ)、U+2225(PARALLEL TO)の方の字形が変わっている。(実体参照で書いておく。‖→‖, ∥→∥。Vista で見ると字形が異なって見えるはず)
コンバータにCp932を指定してJIS X 0201→Unicodeへのcode pointの変換をすると字形が変わった様に見える。他のコンバータでは問題ないだろう。きっと。
2007/3/5追記
これで意味が通らない人は、

http://www.ingrid.org/java/i18n/unicode.html
http://www.ingrid.org/java/i18n/encoding/ja-conv.html

を参照のこと。


(2)文字が追加される case1
UTF-8で3バイト、UTF-16で2バイトに符号化される範囲の未定義だったcode pointに、新たに文字が定義された。
アプリケーションで気をつけることは多くない。
文字種チェックのロジックがすでに入っている場合は、それが正しく機能するかを確認する必要はある。
他のシステムとの連携があってそちら側がShift-JISしか受け付けませんよ、という様なケースでは当然どこかにデータの範囲をチェックするロジックがあるはず。入力時に入れさせないのか、出力時に下駄(〓)にするのかという選択肢はあるだろうが、いずれにせよチェックは必ずしている。
Javaでコード変換の時に'?'になるからそれに任せてしまえ、みたいな対応をしていたりして……。


(3)文字が追加される case2
UTF-8で4バイト、UTF-16で4バイトに符号化される範囲のcode pointに、新たに文字が定義された。
極端なケースを挙げると、漢字1文字を格納する領域(DB上の項目とかメモリ領域とか)として、UTF-8での符号化を前提に3バイトしか確保していない、なんて対応をしていると問題がある(というか、今までも問題はあったのだけど表面化していないというだけである)。
UTF-16での符号化を前提に1文字あたり2バイトしか確保していない、などはいかにもありそうである。10文字の入力に対して20バイトを確保しておいてそれでOKとしているようでは危ない。
ところで、まさかとは思うけど、UTF-16が"1文字を2バイトに"符号化する方法だといまだに思っている人はいない……よな?


ちなみにUTF-8で3バイトに符号化されるcode pointの範囲は、UTF-16では2バイトになる(逆は当然真ならず)。UTF-8で4バイトに符号化されるcode pointの範囲はUTF-16では4バイト必要だし、逆もまた真。


Javaって文字の内部表現はUnicodeじゃなかったっけ

Javaについては、とりあえず資料だけ探しておいて、

JIS2004で追加になった文字をJavaで扱う

にリンクを書いた。一筋縄ではいかなさそう。


Webはどうなるの?(実体参照編)

HTMLでの扱いは色々と考える部分がある。
まず実体参照*3。HTML自体はEUC-JPで書かれたものであっても実体参照として 𪚲 と書くと…… 𪚲 となってフォント次第では表示可能。これはdankogaiさんのエントリを読み直していて気がついた。
まず、この文字を表示可能なフォントがインストールされていることが大前提。


(1)Firefoxの場合
実体参照が解決されその漢字が表示される。ブラウザのフォントを特別指定していなくても——つまりMSゴシックなどを指定していたとしても、その漢字の部分だけ別なフォントで表示される(フォント内のメタデータ(?)の Unicode Range を参照して、表示可能なフォントを探し出しているのか?)。


(2)IE6の場合
フォント設定で、表示可能なフォントを設定しておく必要がある*4
UTF-8,UTF-16をcharsetに指定したHTMLで、UTF-8/UTF-16で3バイト/2バイトに符号化される文字は表示可能だが、UTF-8およびUTF-16で4バイトに符号化される文字は表示できない。中黒(・)の様な表示。
shift_jis, EUC-JPをcharsetに指定したHTMLでは表示できない。


(3)IE7(WinXP)の場合
フォント設定で、表示可能なフォントを設定していない場合。
IE6のUTF-8,UTF-16をcharsetに指定したHTMLと同じ様に表示がされる(shift_jis, EUC-JPをcharsetに指定したHTMLであっても)。


フォント設定で、表示可能なフォントを設定した場合。
UTF-8,UTF-16をcharsetに指定したHTMLはIE6と同じ表示。
shift_jis, EUC-JPをcharsetに指定したHTMLはUTF-8およびUTF-16で4バイトに符号化される文字もちゃんと表示できる。
なんでshift_jis, EUC-JPの方が表示される範囲が広いんだ? なんでだ……??


(4)IE7(Vista)の場合
初期状態で MS ゴシックファミリーがフォント設定されている。
shift_jis, EUC-JP, UTF-8, UTF-16 のどれであっても実体参照から正しい文字が表示される。
ただ、UTF-8, UTF-16 だとゴシックで表示されないんだよなぁ……。ちょっと不思議。


(5)表示はできないものの……
表示できないがしかし、選択してコピーするとちゃんと「その文字」である。メモ帳あたりにペーストして、UTF-8やUTF-16("UNICODE"という名前になっている。ややこしい)で保存すると正しい符号になる。


Webはどうなるの?(UTF-8, UTF-16編)

追記予定
とかいって枠を開けておいたものの、実体参照編と同じ結果になった。そりゃそうか。


Webはどうなるの?(フォーム編)

JIS2004とは全然関係ない話だけど*5、まとめてここに書いておく価値はあると思う。
shift_jis や EUC-JP で書かれたページのフォームに、Unicodeにしか無い文字を入れたらどのように振る舞うのか?
例えば、𪚲 (月に亀)の文字を入れると、

p=%26%23173746%3B

という様なCGIパラメータがわたされる。%26が'&'を、同様%23が'#'を、%3Bが';'を示し、CGI関連のライブラリはこれを"𪚲"という文字列に変換するだろう。これは実体参照の形に他ならないが、ここからUnicodeのcode point U+02A6B2 の文字だと認識して処理することは普通やらない。
と書いたのは、フォームを置いてあるページが shift_jis や EUC-JP で符号化されているケースだから。これをどう処理するかはCGI次第。少なくとも、無駄な負荷が発生してCGIの結果が返ってこない、なんていうことにならないようにはしたいものだ。
UTF-8 や UTF-16 で書かれたページのフォームに入力される場合は、書くまでもなくその方式で符号化されて、

p=%69%D8%B2%DE

とか、

p=%F0%AA%9A%B2

などと来ることになる。


どんなアプリケーションが危ないの?

フロントエンドがUTF-8のcharsetで、バックエンドがshift_jisなシステムなんていうシステムを考える。受け取った入力(画面,ファイル,CGIパラメータなどなど)は途中まで内部コードがUnicode*6で処理されるだろう。どこかでshift_jisに変換しなければならないが、その時に(それはないだろうとも思うけど)Unicodeにしか無い文字があることを失念していたり、今回追加になる範囲のcode pointを考慮していないとか(こちらはありそう)そんなことがあると、どこかでおかしくなる。
このあたりをよく考慮せずにJavaで作っていたりすると途中で'?'に化ける。で、SQLに like '?%' みたいな条件が入って誤ヒットとか起こしそう。


編集のために

UTF-8/UF-16で4バイトに符号化される文字を扱うには、実はメモ帳がよい。Unicode対応したとされている秀丸やEmEditorでも、その様な文字を使うと正しく符号化されないように見えた。
秀丸については現時点でβテスト中のバージョンを以て改善される様だ


もっと深く知るために

下のエントリの本がオススメ。

電脳社会の日本語 [tech][book]

読了。とはいえちょっと読み急ぎすぎたか、理解不足の感あり。
まずはクイズです。「裏」の部首はなんでしょうか? 答えはエントリ末にて。

電脳社会の日本語 (文春新書)

  • 作者: 加藤 弘一
  • 出版社/メーカー: 文藝春秋
  • 発売: 2000-03
  • ASIN: 416660094X
  • メディア: 新書
  • amazon.co.jp詳細へ

第二章 アルファベット世界への参入
1byteが5bitや6bitだった時代、アルファベットの符号がアルファベット順じゃなかった時代の話を読めるのが新鮮。

p57〜p58
ASCIIは制御符号と文字を分離しているだけでなく、アルファベットをAからZまで連続して配置している。
五ビットないし六ビットコードのコンピュータがほとんどだった時代に、あえて七ビットコードにしてた点も重要である。(略)
たが、制定時点では、六ビットのままでよいという反対論が強かった。(略)ANSIが七ビットコードを選んだのは英断というほかない。


第三章 国際文字コードとしての漢字
(特に漢字において)「文字」とは一体どういう概念を示すのか?
コンピュータが電子計算機だった時代に、いずれ文字や文章をデータとして扱うことを予見していた先達達の記録。
よくよく考えてみれば、文字コードの制定というのはコンピュータで漢字が扱える様になる前の話なわけで、例示字体*7は様々な写植・書体の切り貼りと手書きで作成されたという。そりゃそうか、と思ったが今まで気がつかずにいたのがちょっと恥ずかしい限り。


第四章 漢字制限論争の亡霊
「かな漢字を棄ててすべてローマ字にするべきだ」という明治時代に起こった運動。
まさかそれが1980年代まで——否、今現在まで影響を及ぼしていようとは。
これも正直考えもしなかった歴史がある、ということに圧倒される。
シフトJISの思わぬ普及と、83JISによる大混乱。
日本語を取り巻く様々な「流れ」を知る資料である。


第五章 グローバルスタンダードをめぐる攻防
このあたりからやっとなじみの話が出てくる。
ユニコードの理想。甘い見通しによる迷走。結局、サロゲートペアを使った拡張が様々な世界に影響を与えつつある。上のエントリで書いたJIS2004対応フォントなど、まさにその発露。


第六章 文字コードの現在
といいつもすでに過去の一時点になってしまっている。この本全般に言えることだが、書かれた時期が少し古いために、「現在への流れ」を多少なりとも念頭において読まねばならないのがちょっと苦痛ではある。
第二版の刊行を望む。それほどにまとめられた貴重な資料だと思う。


さて、クイズの答え。
「裏」の部首は「衣」である。

p187
「裏」が(略)「衣」だとはなかなかわからない(上下に割った「衣」の間に音符の「里」をはさんだ字形で、横に並べると「裡」になる)。

ちょっとびっくり。哀衰喪衷嚢褒蓑簑簔袁袞袤裹襃襄褻裵。このあたりは全部「衣」が由来。


最後に印象的だった、そして深く頷いてしまった言葉を。

p200
ユニコードは国際化のための文字コードというより、地域化を能率的におこなうために作られた文字コードと考えた方がいいだろう。


きっと、また読むことになるだろう。面白かったし、ためにもなった。

*1 後述する本「電脳社会の日本語」p86には「逆説的に規格票の例示字形に規範的な重みをあたえる結果になった。個々の漢字の『文字概念』は例示字形を唯一の手がかりに推定するしかないからである。」とある。JISが「コードが振った」のは字形に対してでなく「文字概念」なるものに対してであった。にもかかわらず「文字概念」そのものの説明が欠けていた、という趣旨である。このことは現在に至るも影響が少なくないように思う。

*2 技術的な問題ではない、という意味。文化的な問題は非常に大きい。

*3 ここではないどこかで「それは実体参照じゃない。数値文字参照と呼ぶんだ」というツッコミを見かけました。その通りで、数値文字参照と書くべきです。と追記しておく。

*4 と書いてはみたものの、UTF-8,UTF-16をcharsetに指定したHTMLのレンダリングは言語日本語で指定したフォントを必ず使うわけじゃないのか? 判らなくなってきた……。

*5 IE7とも関係ない。IE6でもFirefoxでもずっと昔からこういう動作をしていたはずだから。

*6 UTF-8でもUTF-16でもJavaでもなんでもよいので"Unicode"と表記。

*7 なんで例示字形じゃないんだろう? と頭をひねっていた。誰か教えてくださいませ。