Unicodeにおける全角・半角の概念を解説します。
全角と半角という用語は印刷とか組版の用語なんだそうです。
全角は文字の縦横比が1:1、半角は2:1ということらしいです。
Shift_JISのようなANSIエンコーディングでは、
慣例的に全角文字が2バイト、半角文字が1バイトといった割り当てがなされています。
よくある「全角文字は500文字以内、半角文字は1000文字以内」といったような文字数制限はまさにその現れです。
こういった状況から「全角=2バイト文字、半角=1バイト文字」という固定観念があるようです。
しかし、EUC_JPなどでは2バイトでも半角の文字もあることから、
いかなる状況下でも上記の関係が成り立っているわけではありません。
そもそも、文字エンコーディングがグリフに対してエレメントを何個割り当てるのかという問題と、
グリフ(字形)のもつ属性(縦横比)という問題は何の因果関係もありません。
両者は全くもって別の問題です。
例えば、"あ"というグリフはいかなる文字エンコーディングで表現しても全角ですが、
"あ"に対して割り当てるエレメントの数は文字エンコーディング次第です。
Shift_JISなら1byteのエレメントを2つで2バイト、
UTF-8なら1byteのエレメントを3つで3バイトとなっています。
とりあえず、Unicodeを扱うにあたっては「全角=2バイト文字、半角=1バイト文字」という固定観念は捨てるべきです。
UnicodeコンソーシアムはEastAsianWidthという付則を定めています。
これは、各グリフがどのように描画されるべきかという属性を定めています。
当然ですがエンコーディングは一切関係しません。
以下に属性値と説明を列挙します。
全角に該当する文字。文字の名前に"FULLWIDTH"と付く。
具体的には全角英数などが該当する。
半角に該当する文字。文字の名前に"HALFWIDTH"と付く。
具体的には半角カナなどが該当する。
F以外で全角に該当する文字。
具体的には漢字、ひらがな、カタカナなど。
H以外で半角に該当し、対応する全角文字が存在する文字。
具体的には半角英数などが該当する。
曖昧。文脈次第で全角・半角かが変わる。
東アジア圏では全角として扱われることになる。
具体的にはギリシア文字、キリル文字などが該当する。
中立。そもそも東アジア圏に存在しない文字。
アラビア文字などが該当する。
やたらと属性値が出てきましたが、描画にあたってはそれほど複雑ではありません。
全角:F、W、A
半角:H、Na、N
全角:F、W
半角:H、Na、A、N
※本来は全角という概念が出てこない
つまり、ロケールに応じてAmbiguousに該当する文字の描画幅が変わるだけです。
Ambiguousに該当する文字は従来の東アジアの文字セットに出現しているものだけです。
たとえば、気息記号のないギリシア文字はAmbiguousになりますが、気息記号付きはNeutralになります。
また、アルファベットでは気息記号無しはすべてNarrowですが、
気息記号のあるものについては、一部が中国語(ピンイン)などで出現するためAmbiguousとなりますが、
それ以外はNeutralに該当するという複雑な状況です。
Unicodeコンソーシアムで公開されている資料があります。
http://www.unicode.org/Public/5.0.0/ucd/EastAsianWidth.txt
DelphiではDEKOさん作のMECSUtilsに判定を行える関数が収録されています。
(MecsEastAsianWidth関数、MecsIsFullWidth関数など)