覚書
この覚書で使用されている表記法
文字コードは全て16進数で表す。Unicode Consortium が発行する文書の正式なコードポイントの表現法は
U+10FFFF
U+
” に続けて16進で書く。Unicode の文字コードの範囲は U+0000
から U+10FFFF
である。U+
” を省略する。1F469:200D:2764:200D:1F469
:
” で区切るが、(コード列である事が文脈から明らかな場合には)通常の習慣に従って1F469 200D 2764 200D 1F469
0000~10FFFF
~
” を使う。(~
の右、この例では 10FFFF
を含む)FFFE,FFFF
,
” で区切る。
Unicode Consortium 推奨の正規表現の中では文字コードを
\u{1F469}
\u
” に続けて波括弧(curly bracket)の中に16進数で書かれる事がある。この利点は紛れが少ないことにある。従って、状況に応じて、この表記を使う事もある。
文字コード列を厳密に(しかも記号を使って簡潔に)表現したい場合に、しばしば正規表現が使われる。ここではその表現法の一部を借用する。借用したのは
X Y # the sequence consisting of X then Y X* # zero or more occurrences of Y X+ # one or more occurrences of Y X? # zero or one occurrence of Y (X) # for grouping X|Y # either X or Y . # a code point
#
” より右はコメントである。X
とか Y
は正規表現が使われている場所で(必要に応じて)説明されているはずである。
このページでは Unicode の仮想的なテキストを話題にする。
Unicode の文字コード(character code)は (16 進数で) 0
~ 10FFFF
である。
Unicode テキストとは Unicode の任意の文字コード列である。0
~ 10FFFF
の整数の集合は (Unicode の)コード空間(codespace)と呼ばれる。これは 21bit の空間である。
コード空間の各要素は code point と呼ばれる。以下単にコードあるいは文字コードと言う。各コードは抽象文字を表している。
On a computer, abstract characters are encoded internally as numbers. To create a complete character encoding, it is necessary to define the list of all characters to be encoded and to establish systematic rules for how the numbers represent the characters.
The range of integers used to code the abstract characters is called the codespace. A particular integer in this set is called a code point. When an abstract character is mapped or assigned to a particular code point in the codespace, it is then referred to as an encoded character.
文献[7] p.29 より引用
説明に出てくる「抽象文字(abstract character)」は難しい概念である。「抽象」の理解は後回しにして、ここでは単に「文字」とする。世界中には多くの文字が存在し、既に Unicode として登録されているものもあれば、まだ登録されていないものもあるだろう。登録されコードが割り当てられているものを符号化文字(encoded character)と言う。
コード表は、コード空間の要素(code point)を符号化文字に対応づける。
図1: 符号化文字
Unicode のコード空間は議論の便宜上 Plane0 ~ Plane16 の領域に分割される(表1)。
Plane | description |
---|---|
P0 | Basic Multilingual Plane (BMP) |
P1 | Supplementary Multilingual Plane (SMP) |
P2 | Supplementary Ideographic Plane (SIP) |
P3 ~ P14 | Reserved |
P15 | Supplementary Private Use Area-A |
P16 | Supplementary Private Use Area-B |
Blocks.txt
の方が実用的かも知れない)
なぜ「抽象文字」と言うのか? Unicode 標準では、例えば文字 \(c\) (ここに \(c\) は任意の抽象文字を代表している)に関しては
(a) \(c\) の字形(glyph)は問題にしない
(b) テキストの中での文字 \(c\) の果たす役割や、処理のされ方を問題にする
そのために英単語(例えば fox)の構成要素としての “x” と、数式の中で変数名として現れる “\(x\)” は違う文字と扱われる。前者は letter に、後者は symbol に分類され、そして文字コードも異なる。(役割が違うから異なる字形で描かれているのであって、その逆ではない)
Unicode の説明では、コード表はコードに文字をマップさせているのだが、“character” の意味について曖昧性を残している。
The core of a character code standard is a mapping of code points to characters, but in some cases the semantics or even the identity of the character may be unclear. Certainly a character is not simply the representative glyph used to depict it in the standard. For this reason, the Unicode Standard supplies the information necessary to specify the semantics of the characters it encodes.
文献[7] p.905 より引用
具体的に何を言っているのか注意して見ていくことにしよう。
Unicode のコード表は code point の役割を定義している
抽象文字が割り当てられていない code point が存在する。
Not all assigned code points represent abstract characters; only Graphic, Format, Control and Private-use do. Surrogates and Noncharacters are assigned code points but are not assigned to abstract characters.
文献[7] p.30 より引用
もっと具体的に言えば
FFFE,FFFF
NoncharactersE000~F8FF
Private Use AreaD800~DFFF
Surrogate Codes
現実のテキストはファイルに収められ、ファイルの最小単位は 8bit(1byte) である。またテキストメッセージを送信する場合も同様である。従って、コード列を何らかの方法で byte 列に変換する必要がある。この方法には UTF-8, UTF-16, UTF-32 の3通りあるが、UTF-8 以外は淘汰されるはずである。しかし、この問題に関してはここでは取り上げない。「仮想的」と述べたのは変換前のコード列のままのテキストを話題にしているからである。
文献[7] p.18 からの引用
Plain text is a pure sequence of character codes; plain Unicode-encoded text is therefore a sequence of Unicode character codes.
図2に、Unicode の一部(先頭部分)を載せる。この部分は ASCII 文字コードに対応しており、ラテン文字の基礎になっている点と、プログラミング言語の基礎になっている点で、基本的である。
図2: http:U0000.pdf
文字 “a
” は、006
と書かれた列と 1
と書かれた行の交差位置にあり、“a
” の下に小さく 0061
と表示されている。この 0061
が “a
” の文字コードである。16進数で表記されている。Unicode の文字コードは4桁の16進数で表現するのが習慣である。(4桁で表せない場合は、桁を追加する。最大で10FFFF
である)
説明によると表に示されている文字(A,B,C など)はグリフであるとされている。
Unicode ではグリフ(glyph)とは文字(character)の視覚的な表現であると説明されている(文献[7] p.6)。日本語に翻訳すると「字形」に相当する[5]。
Unicode 標準は Characters を扱うのであって、グリフは問題にしていない。
The difference between identifying a character and rendering it on screen or paper is crucial to understanding the Unicode Standard’s role in text processing. The character identified by a Unicode code point is an abstract entity, such as “latin capital letter a” or “bengali digit five”. The mark made on screen or paper, called a glyph, is a visual representation of the character.
The Unicode Standard does not define glyph images. That is, the standard defines how characters are interpreted, not how glyphs are rendered. Ultimately, the software or hardware rendering engine of a computer is responsible for the appearance of the characters on the screen. The Unicode Standard does not specify the precise shape, size, or orientation of on-screen characters.
グリフの説明
文字自体は抽象的な存在なのであるが、見えるようにするためには形を持たなくてはならない。
例えば文字 “a” にしても、様々な形(デザイン)の “a” があるのだが、そのうちの一つがコード表に例として示されているにすぎないのである。従って文字コード 0061
の文字の形は、コード表に示されている字形のもののみならず、アルファベットの小文字の “a” であると考えられる文字は全て該当するのである。
Unicode ではグリフに関する説明が含まれるのであるが、ASCII コード表にはそれに類する説明は含まれていなかったと思う。ASCII コードは 100 個に満たない図形文字(視覚的に表現できる文字)を扱っているのであり、その中では文字の字形の細かな違いを問題にする余地はなかったのである。しかし Unicode は膨大な文字を扱う。コード表で示されている文字は何であるのか、注意書きが要求されるようになったのであろう。
U0000.pdf
には 0000
から 007F
までが載っている。この内 0000
から 0020
、および 007F
は他の文字と性格がかなり異なる。他の文字のように字形を持っていない。表示装置の中で、後続する文字の配置位置を制御するのに使われているので制御文字と呼ばれている1。
以下の制御文字はテキストファイルの中で次の意味を持つ。
0020
: 1文字分の空白を表す0009
: TAB を表す000A
: 改行を表す (unix 系 OS の場合2)
000D:000A
、古い MacOS (OS9 まで) は 000D
である。:
”で連続した Unicode を表している。
Unicode の標準化組織 Unicode Consortium は Unicode[6] に関する膨大な文書を発行している。これらの文書は Unicode 標準に関する全ての信頼できる情報源であると言ってもよい。
規格文書は Unicode のバージョンごとに纏められている。現在の最新バージョン 10.0.0 であるが、この記事を書いている時点(2017/07)では PDF 版の解説記事の最新版は 9.0.0 である。以下の説明は、これに基づく。
文献[7]はもっとも基本的な Unicode に関する文献である。補足的な説明が文献[8]にある。
Unicode の個別の文字について調べたい時には文献[9]が基本的でる。文字コード別に文字が分類されている。PDF ファイルであるために見やすい事は見やすいが、あまり実践的ではない。
もっと使いやすいのは文献[10]である。テキストファイルなので、grep
や awk
を使えるのが嬉しい。
用語の日本語訳はできるだけ文献[11]に従ったが、さらに簡略化した言い方をしている場合もあるので注意されたい。
“?” は “question mark”.
“$” は “dollar sign”.
疑問: “mark” と “sign” はどのように使い分けられているのか?
UnicodeData.txt
の一部を載せると、
001E;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;; 001F;<control>;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;; 0020;SPACE;Zs;0;WS;;;;;N;;;;; 0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;; 0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;; 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;; 0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;; 0026;AMPERSAND;Po;0;ON;;;;;N;;;;; 0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;; 0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;;
のようになっている。
このファイルのデータ構造を簡単に紹介する。
;
” で区切られている。→ 以下フィールドを $1
、$2
、... とする$1
は文字コード。(16進数表示)$2
は文字名$3
は文字区分
「文字区分」については文献[4]に解説がある。
Unicode では表2に示すように文字を7つに分類している[4]。
ここでは ASCII 文字集合(Unicode の 0000
~ 007F
)の範囲で、この分類について考えてみる。この範囲の文字コードのPDF版は次の文献[1]に載っている。
なおここでは4桁の16進数は、文字コードを表すとする。
abbr | long name | category values |
---|---|---|
L | Letter | Lu Ll Lt Lm Lo |
M | Mark | Mn Mc Me |
N | Number | Nd Nl No |
P | Punctuation | Pc Pd Ps Pe Pi Pf Po |
S | Symbol | Sm Sc Sk So |
Z | Separator | Zs Zl Zp |
C | Other | Cc Cf Cs Co Cn |
0
”, “1
”, ..., “9
” である0020
)のみ
定義: 図形文字
図形文字とは形を持つ文字だと考えて良い。表2の
なお Zs に属する文字は以下の通り
% awk -F ';' '$3 ~ /Zs/ {print}' UnicodeData.txt 0020;SPACE;Zs;0;WS;;;;;N;;;;; 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;; 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;; 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;; 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;; 2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;; 2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;; 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;; %
“MARK” とか “SIGN” とかを、まずは ASCII 文字集合の中で吟味するのであれば、“Punctuation” と “Symbol” だけが関係する。
ASCII 文字集合の中で、“Punctuation” には次の文字が含まれる。
! 0021 EXCLAMATION MARK " 0022 QUOTATION MARK # 0023 NUMBER SIGN % 0025 PERCENT SIGN & 0026 AMPERSAND ' 0027 APOSTROPHE ( 0028 LEFT PARENTHESIS ) 0029 RIGHT PARENTHESIS * 002A ASTERISK , 002C COMMA - 002D HYPHEN-MINUS . 002E FULL STOP / 002F SOLIDUS : 003A COLON ; 003B SEMICOLON ? 003F QUESTION MARK @ 0040 COMMERCIAL AT [ 005B LEFT SQUARE BRACKET \ 005C REVERSE SOLIDUS ] 005D RIGHT SQUARE BRACKET _ 005F LOW LINE { 007B LEFT CURLY BRACKET } 007D RIGHT CURLY BRACKET
“Symbol” に含まれるのは以下の文字である。
$ 0024 DOLLAR SIGN + 002B PLUS SIGN < 003C LESS-THAN SIGN = 003D EQUALS SIGN > 003E GREATER-THAN SIGN ^ 005E CIRCUMFLEX ACCENT ` 0060 GRAVE ACCENT | 007C VERTICAL LINE ~ 007E TILDE
どうやら “question mark” の “MARK” と言うのは句読点類を意味しているらしい。しかし、ならば
# 0023 NUMBER SIGN % 0025 PERCENT SIGN & 0026 AMPERSANDは何故 “Symbol” ではなくて “Punctuation” に分類されているのだろう?
アクセントに関する次の文字はどうなんだろう?
^ 005E CIRCUMFLEX ACCENT ` 0060 GRAVE ACCENT ~ 007E TILDE
「文字区分」で “Mark” に属する文字を調べると、これらはアクセントマークなのである。アクセントは記号なのかマークなのか?
この3つが “Punctuation” ではなく “Symbol” に分類されたのは、文字としての現実の使われ方(1つの独立した記号として使われている)からだろうか?
結局、疑問が解けない...
MARK と SIGN はどのような基準で分けているの? → 以下の補足1と補足2を見よ
補足1: “@
”, “#
”, “%
”, “&
”
この話は文献[4]でも取り上げられている:
The distinctions between some General_Category values are somewhat arbitrary for edge cases, particularly those involving symbols and punctuation. For example, a number of multiple-function ASCII characters, including “@”, “#”, “%”, and “&”, have long been classified as Other_Punctuation (gc=Po), although they are not among the characters used as punctuation marks in traditional Western typography.
つまり、UnicodeData.txt
では “@
”, “#
”, “%
”, “&
” は punctuation として分類されてはいるが、伝統的な西洋のタイポグラフィでは punctuation 扱いはされていないと。
補足2: “^
”, “`
”, “~
”
これらの記号は U0300.pdf
にも載っている。
つまり、U0000.pdf
の方は、独立した1文字(つまり記号)であって直前の文字を修飾する意味を失っている。他方 U0300.pdf
に現れる記号
0302
COMBINING CIRCUMFLEX ACCENT0300
COMBINING GRAVE ACCENT0303
COMBINING TILDE
なお、0300
とよく似たものに 0340
(Vietnamese tone mark の COMBINING GRAVE TONE MARK) があるが使わないようにとの御達しである。0341
も同様。
また 0303
と形が似ているものに 0342
(COMBINING GREEK PERISPOMENI) があるが、 “Greek-specific form of circumflex for rising falling accent” と注釈されている。これは生きているらしい。ギリシャ文字の中で、0303
とは異なるニュアンスで使われているのかも知れない。
ネットで調べると「文字」の英訳として “character” と “letter” があるらしい。
そして、“character” は表意文字、“letter” は表音文字であるとされる。多分、大ザッバにはそれで良いのだろう。
実際に、Unicode での文字分類を調べると、Letter については以下のような表現に出会う。
GREEK CAPITAL LETTER
HIRAGANA LETTER
KATAKANA LETTER
HANGUL LETTER
また、漢字に関しては、Unicode表[2]では “ideographs” としているが解説記事である[3]には “ideographic character” と表現されている。
これらは、“letter” は表音文字、“character” は表意文字、の解釈と矛盾していない。
しかし何だかしっくり来ないのだ。
何がしっくり来ないのか? letter と character との関係である。Unicode は character code を扱っているのである。その code の中で letter が扱われている。となれば letter なるものは(集合論的には) character の一部である。「character は表意文字で... letter は表意文字ではない」とは行かないのである。
Unicode で言う character は日本語の「文字」に近い意味で語られているのではないかと思える。(いやそう考えないと辻褄が合わない)
そのために、表意文字を言い表したい場合には “ideograph” と言うのであろう。
これで一件落着? --- いや、そうでもない
前節「MARK? or SIGN?」の表2「文字区分」の中に “Letter” が存在する。そして “UnicodeData.txt
” では個々の文字の文字区分が個別に示されている。CJK Ideograph については、纏めて次のようになっている。
4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;; 9FEA;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
説明を繰り返すが、フィールドは “;
” で区切られている。第1フィールドは文字コード、第2フィールドは説明、第3フィールドは文字区分であり、“Lo
” は “Other Letter” の意味である。つまり “Letter” として分類されているのである。これはどう解釈したら良いのか?
どうやら “Character” とか “Letter” を世の常識通りには受け取らない方が良いらしい。
これらの文字については、Unicode の独自の意味があって、それは歴史的に形成されたものだ。
コンピューターの誕生と共に「文字コード(character code)」が定義され、そこでアルファベットは “Letter” に分類されたと思う。そして今は多言語を扱う Unicode の時代である。Letter の意味がそれとともに変化したと考えたらよかろう。
文字が表音なのかそれとも表意なのかは文字(character)分類にとっては小さな問題なのであろう。
表音文字 phonogram
表意文字 ideogram or ideograph
注意: phonograph は蓄音機
Phonetic symbol
定義: 結合文字 (combining character)
“combining mark” とも言われる。
結合文字は表[2]の文字区分 Mark
の値によって3つに分類される[4]:
Mn: a nonspacing combining mark Mc: a spacing combining mark Me: an enclosing combining mark
ややこしいのは、紛らわしい言葉使いが、文献[4]とは別に定義されている事だ。
D53 Nonspacing mark: A combining character with the General Category of Nonspacing Mark (Mn) or Enclosing Mark (Me).
文献[7] D53 p.106
これによると “Nonspacing mark” は Mn
と Me
を含むが、“Nonspacing Mark” だと Mn
だけである。"nonspacing combining mark" は後者の意味である。従って意味するところを “Mn
” や “Me
” を使って必ず補足すべし。
定義: 基底文字(base character)
結合文字以外の図形文字
カタカナは
図3:
Unicode 表の PDF ファイルには表だけではなく、個々の文字に関する説明も含まれている。
図4: 「タ」と「ダ」の説明
図4に現れる「≡」は等価(equivalence)を表している。つまり「ダ」は一つのコード(
図5:
ここで取り上げた「ダ」問題は多分に誤解を招いたかも知れない。
結合文字を導入する意図が見えてこない。
結合文字を導入した結果が、結合文字なしの1コードで表現できるならば結合文字を導入するメリットは何か? 複雑さを増やしただけではないか?
結合文字を導入するメリットがあるとすれば、新しい字形を生み出す力である。例えば、「タ」に半濁点を添えることは形式的に可能である。それが意味を持つか否か、意味を持つとしてもフォントが存在するか否かは別の問題である3。でも或る作家が出版社に対して、(登場人物の癖のある発音を表現するために)似たことを要求するかも知れない。
結合文字を導入する意図はラテン文字の扱いを見ると見えてくる。
ラテン文字にはしばしばアクセントマーク(accent mark)が現れる。
図6に、そうしたアクセントマーク付き文字の一部を示す。コードが8bitで収まるので、これらはASCII文字コード表と共に広く使われてきたのではないかと思える。
図6:
アクセントマーク付きのラテン文字は次のPDFファイルに現れる。
2つのアクセントマークが付いたラテン文字も存在する。
アクセントマーク付きのラテン文字は結合文字を使っても表現できる。2つのアクセントマークが付いている場合には2つの結合文字を使って表現すると考えるのが自然である。
図7はラテン系のアクセントマークのテーブルである。(全てではない)
図7:
点線で表された円がアクセントマークが作用する文字を表している。
図7の結合文字
ちょっと変わった結合文字の例が文献[7] p.56に載っている。
☡
さらに p.112 には
文字 a に作用させてみる:
囲みマークで生成された文字は記号のように見えるが、必ずしも記号ではない。その事が文献[7] p.57 に次の図で示されている。
文字 “
この例は、同じ字形をしているからと言って同じ文字とは限らない事を示している1。使い方まで問題にされているのである。
文献[7]には “combining character” と “combining mark” の2種の言い回しが見られるが、この2つの用語はどのように使い分けられているのか?
次の説明がある。同じと見て良いだろう。
文献[7] p.105 より引用
combining character の使い方
文献[7] p.55 より引用
script: 文献[11]では「用字」と訳している。"Cyrillic script" とか “Latin script” のような使い方をする。言語ごとの文字集合とその使い方と理解すれば良いだろう。(詳しくは tr24)
base character: 文献[7] p.105 より引用
表2の中の、Letter (L)、Number (N)、Punctuation (P)、Symbol (S)、Space Separator (Zs)を指す。
combining character は
“combining character” は文字の断片に過ぎず、これを character の部分集合と見なすには問題がある。
そもそも「文字コード表(character code table)」と言うから分かり難くなるのだ。
Unicode テキストはコードポイントの列である。結合文字の存在は 2つの Unicode テキストの同等性の比較を複雑にする。結合文字列の概念は、この問題の解決のために導入されている。Unicode テキストは結合文字列を単位として細分化し、結合文字列を単位として両テキストと比較する。(→ Unicode normalization)
定義: 結合文字列(combining character sequence) p.107
注釈: 結合文字列の定義の中に
\(X\) を結合文字列の集合とする。この時、\(f(X)\) は
\(f(X)\) について呼称が欲しいが...
図8: 結合文字列から得られる文字
コメント:
結合文字列に類似の概念がありすぎる!
たぶん「合成文字」のような言葉が必要なのだろう。
定義: 拡張基底文字(extended base character)
定義: 拡張結合文字列(extended combining character sequence)
結合文字列(combining character sequence) は文字か? 文献[12]より
書記素(grapheme): ある言語の書記体系の最小単位;英語のアルファベットの各文字など. (Goo 辞典より)
ユーザ認知文字(user-perceived character)
ユーザが1文字と考えているもの(ユーザ認知文字)は必ずしも 1 つのコードポイントに対応しない。次の書記素クラスタに近い。
書記素クラスタ(Grapheme cluster) 文献[13]
我々がテキストを編集する時に1文字として扱いたいものと考えてよい。
定義: grapheme extender
文献[7] D59 p.108
GE(grapheme extender) は
定義: grapheme base 文献[7] D58 p.107
文献[7] D59 p.108
書記素クラスタには2種ある。一般に拡張書記素クラスタが推奨される。
定義: Legacy grapheme cluster/p>
The base can be single characters, or be any sequence of Hangul Jamo characters that form a Hangul Syllable, as defined by D133 in The Unicode Standard, or be a pair of Regional_Indicator (RI) characters. For more information about RI characters, see [UTS51].
The continuing characters include nonspacing marks, the Join_Controls (U+200C ZERO WIDTH NON-JOINER and U+200D ZERO WIDTH JOINER) used in Indic languages, and a few spacing combining marks to ensure canonical equivalence. Additional cases need to be added for completeness, so that any string of text can be divided up into a sequence of grapheme clusters. Some of these may be degenerate cases, such as a control code, or an isolated combining mark. 文献[13]
注釈: any sequence of Hangul Jamo characters
定義: 拡張書記素クラスタ(Extended grapheme cluster) 文献[13]
以上を纏めると次の図のようになる。(制御文字を除く)
図9: Extended Grapheme Cluster (推定図)
接合子(joiner)
接合子は文字合成のための演算子である。
現状では接合子は(Mac においてさえ)十分にサポートされているようには見えない。その事が理解を困難にしている。(実験で動作を確認できない😔)
ゼロ幅接合子(Zero width joiner): 文献[7] p.828
ゼロ幅非接合子(Zero width non-joiner): 文献[7] p.829
ゼロ幅接合子とゼロ幅非接合子は書式制御文字である。 文献[7] p.831
Combining Grapheme Joiner:
Formally, the combining grapheme joiner is not a format control character, but rather a combining mark. It has the General_Category value gc=Mn and the canonical combining class value ccc=0.
As a result of these properties, the presence of a combining grapheme joiner in the midst of a combining character sequence does not interrupt the combining character sequence; any process that is accumulating and processing all the characters of a combining character sequence would include a combining grapheme joiner as part of that sequence. This differs from the behavior of most format control characters, whose presence would interrupt a combining character sequence. 文献[7] p.831
例 1:
fallback とは、合体図形が無い場合の代替え図形
このブラウザでの
例 2:
図10: 文献[19]
このブラウザでの
Mac のテキストエディタでは1文字として扱われている。
文献[19]より引用
要約
上から順に
変換上の注意: surrogate pair は禁止
テキストファイル、通信プロトコル、で使われる。
Plan9 manual utf(6)
UTF-8, a transformation format of ISO 10646
surrogate pair は UTF-16 にのみ許される。16bit 空間では不足したので導入された苦肉の策だろう。surrogate pair の導入によって、UTF-16 は 21 bit までのコードを扱えるようになった。Unicode Consortium はコード空間をこれ以上に大きくしないと約束している。
Unicode を Surrogate pair へ変換するアルゴリズムは
もっと計算しやすい Surrogate pair の形式は考えられたろうに...
[1] C0 Controls and Basic Latin (Range: 0000~007F)
[2] CJK Unified Ideographs (Range: 4E00~9FEA)
[3] Chapter 18: East Asia
[4] Table 12. General_Category Values
[5] 常用漢字表における「字体・書体・字形」等の考え方について
[6] The Unicode Consortium
[7] The Unicode® Standard: Version 9.0 – Core Specification
[8] Unicode Technical Reports
[9] Unicode 10.0 Character Code Charts
[10] UnicodeData.txt
[11] Unicode Terminology English - Japanese
[12] Characters and Combining Marks
[13] UAX #29:UNICODE TEXT SEGMENTATION
[14] DerivedCoreProperties.txt
[15] New Character Property for Prepended Concatenation Marks
[16] Emoji
[17] Recommended Emoji ZWJ Sequences, v5.0
[18] Full Emoji List, v5.0
[19] UNICODE EMOJI
に含まれている。先頭部分を図に示す。http:U30A0.pdf
http:U30A0.pdf
30C0
)で与えてもよいし、2つの連続したコード(30BF:3099
)で与えてもよい。「ダ」は単なる例であって、全ての濁点および半濁点付きの平仮名・片仮名に同様に2種類の表現法が成立する。コード 3099
は濁点を表す結合文字である1。結合文字と言うのは、他の文字と結合して新しい文字を形成する符号のことである。半濁点を表す結合文字 309A
も存在する。図5から分かるように、独立した1文字2として濁点を表す 309B
や半濁点を表す 309C
も存在する。
http:U3040.pdf
注1: 濁点を表す結合文字は “COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK”、半濁点を表す結合文字は “COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK” と名付けられている。(U3040.pdf)
注2: 「独立した1文字」の定義は実は非常に難しい。ここでは1文字分のスペースをとると言う意味で使われている。
注3: アイヌ語のカナ表記に「ト゚」が存在し、コード列 30C8:309A
で生成される。「ト゚」は Chrome、Safari、Firefox でサポートされている。(IE は確認していない)
「タ゚」はアイヌ語のカナ表記に存在しない。コード列 30BF:309A
で生成される文字の見え方はブラウザに依存している。Chrome と Firefox は OK だが、Sadari は半濁点の後のスペースの取り方が NG である。
5.3. ラテン文字とアクセントマーク
http:U0080.pdf
http:U0300.pdf
0310
や 0352
で表されているアクセントマークは、2つの要素から構成されているように見えるが、これで1つのアクセントマークであり、分解はできないとされている。他方結合文字 0344
は2つの結合文字 0308
および 0301
を順次作用させたものと等価であるとされている1。
文字 a に作用させて、確認してみよう:
ä -- ä
ä -- ä
ä́ -- ä́
ä́ -- ä̈́
ä́ -- ä̈́
この表示結果はブラウザに依存する。(そして多分OSにも)
Mac で使える代表的な3つのブラウザ、Safari, Chrome, Firefox を試すと正しく表示しているのは Safari のみである。(さすがは Apple。こういうところはキチンとやる。)
注1: つまり結合文字 0344
は要らないはずである。何故このようなものが入り込んでしまったのか? 原理原則が unicode.org で煮詰まっていない時代に入り込んだのだろうと思われる。存在しなくても良い、あるいは存在しないほうが良い文字コードはこの他にもいくつかある。この事は2つの文字の同一性の判定を幾分複雑にする。
5.4. 囲みマーク
☡⃟
これは Safari と Firefox で OK。しかしどちらも結合された文字のデザインが悪い。Chrome は全然ダメ。
呟き2: 図形を描かない囲みマークが欲しい... グルーピングに使える
a⃞
a⃞̈
a⃞̈⃝
Safari はなんとか OK。なかなか上手く納まってくれない。(納めるにはフォントサイズが変わるので難しいだろう)
Firefox も Chrome も全然ダメ。
20DF
,20E0
,20DD
などは結合囲みマーク(combining enclosing mark)と呼ばれ、囲み文字を生成する。このようなものの存在は文字の正規化を複雑にしている。後に触れる。
!
” (0021
) と囲みマーク 20E4
から生成された文字の特性(property)はベースになった “!
” と同じであるとされている。従って句読点文字(punctuation character)であり、記号ではない。記号と句読点文字とでは改行時における禁則処理の方法が異なる。警告マーク(文字 “!” を三角形で囲った記号)はニーズとしてはあるので、記号としての警告マークが 26A0
として別に準備されている。
注1: 同様な事例は Mathematical Alphanumeric Symbols (http:U1D400.pdf)にも見られる。
数式に出てくる「\(a\)」(1D482
) は記号であり、Letter である「a」(0061
)とは違う。後者は語(word)の構成要素として使われるが、記号は単独に使われる。グリフは例示に過ぎない事に注意。
5.5. 結合文字は文字か?
Combining character: A character with the General Category of Combining Mark (M).
All combining characters can be applied to any base character and can, in principle, be used with any script.
Any graphic character except for those with the General Category of Combining Mark (M).
0020
ではなく) 00A0
の使用が推奨される2。
例えば「テキストの中の character の個数を数えなさい」と言われた場合、困る。
“combining mark” に統一し、概念としては “character” から外すのが分かりやすいのではないか?
“combining mark” の和訳 → 「結合符号」で良いのではないか?
ついでに、制御文字類も “character” から外すのが分かりやすい。
そのようにすれば “character” は日常用語の「文字」(グリフの1文字)に近くなる。
ただし「グリフの1文字」は吟味を要する言い方である。
「グリフの1文字」は、日本語や英語(or Latin)でははっきりしているが、世界中の文字の中には怪しいものもあるのではないか?
“Unicode 10.0 Character Code Charts” → “Unicode 10.0 Code Charts”
と呼ぶべし。
注1: 制御文字類: carriage return, tab, or right-left mark など
注2: 文献[7]の “Exhibiting Nonspacing Marks in Isolation” を見よ
5.6. 結合文字列
Combining character sequence: A maximal character sequence consisting of either a base character followed by a sequence of one or more characters where each is a combining character, zero width joiner, or zero width non-joiner; or a sequence of one or more characters where each is a combining character, zero width joiner, or zero width non-joiner.
CCS := BC? (CC|JC)+
DCCS := (CC|JC)+
CCS: combining character sequence
DCCS: defective combining character sequence
BC: base character
CC: combining character (Mn,Mc,Me)
JC: join control1er (ZWNJ|ZWJ) # (200C,200D)
ZWJ
(zero width joiner) と ZWNJ
(zero width non-joiner) が含まれている。これらは一般に Letter に作用する。結合文字列の中でどのように使われるのか? 例が文献[7]の Chapter 12 に含まれている。しかし我々には馴染みの無い script なので理解しずらい。
\[ \{\mbox{encoded character}\} ⊂ f(X) ⊂ \{\mbox{abstract character}\} \]
の関係を満たす。ここに \(f\) はコード表である。
「合成基底文字」のような概念を次のように BNF(Backus-Naur form) で定義する
合成基底文字 := 基底文字 | (合成基底文字:結合文字類)
このようにして「合成基底文字」を定義しておくと、結合文字類が作用する相手は直前の合成基底文字であることを正確に表現できるのではないかと思えるのだが...
EBC := BC|HAN
EBC: extended base character
BC: base character
HAN: Hangul syllable (or Hangul Jamos)
テキストを処理するプログラムの input は任意のコード列と考えるべきである。つまり必ずしも正当なコード列ではない。不正なコードが含まれている場合はプログラムは何らかのエラー処理をしなくてはならない。Hangul black はコード列なので、正当なコード列(Standard Korean syllable block)のシンタックスと、正当なコード列ではないが拡張基底文字とみなせるコード列のシンタックスは異なっていることに注意する必要がある[13]。ここでは、この問題に触れていない。(他の場所で取り上げる)
注意: このように書くと BC
(base character) には Hangul が含まれていないかのように聞こえるが、合成済み Hangul は base character に分類されている。さらに Hangul Jamo も基底文字に分類されていることに注意する必要がある。
Hangul Jamo による Hangul の表現では、複数の基底文字(Hangul Jamo)の列が1つの基底文字のように見え(振舞わ)なくてはならない。これは(これまでの)基底文字の定義から逸脱している。そのために、基底文字の概念拡張が必要とされるのである。
ECCS := EBC? (CC|JC)+
ECCS: extended combining character sequence
EBC: extended base character
CC: combining character (Mn,Mc,Me)
JC: join control1er (ZWNJ|ZWJ) # (200C,200D)
A: That depends. For a programmer, a Unicode code point represents a single character (for exceptions, see below). For an end user, it may not. The better word for what end-users think of as characters is grapheme: a minimally distinctive unit of writing in the context of a particular writing system.
6. 書記素
It is important to recognize that what the user thinks of as a “character”—a basic unit of a writing system for a language—may not be just a single Unicode code point. Instead, that basic unit may be made up of multiple Unicode code points. To avoid ambiguity with the computer use of the term character, this is called a user-perceived character.
...
These user-perceived characters are approximated by what is called a grapheme cluster, which can be determined programmatically.
普通の文字の他に、改行やタブなども編集対象になるであろう。
“grapheme cluster” は書記素を表すコード列である。(書記素の列ではない)
ここでは “grapheme cluster” を定義しているのではなく、概念を説明しているだけである。
日本語では書き言葉の最小単位は文字であり、人々は1文字とは何であるか(教育の結果)認識していると思える。例えば漢字の「明」を構成する「日」と「月」を分離して書くわけにはいかないことなど。
Windows の改行(CR+LF)は、内部の2つの文字を分離させてはならない。まとめて書記素として扱う必要がある。
半角片仮名の「ガ」も書記素として扱われる。(次の grapheme extender の定義を見よ)
そのために、マウスカーソルが「カ」と「 ゙」の間に入らない。
A grapheme extender can be conceived of primarily as the kind of nonspacing graphical mark that is applied above or below another spacing character.
GE := (NM|JC|\u{FF9E}|\u{FF9F}|SMC)
GE: grapheme extender
NM: nonspacing mark (Mn,Me)
JC: join control1er (ZWNJ|ZWJ) # (200C,200D)
SMC: a few spacing mark for compatibility
\u{FF9E}: HALFWIDTH KATAKANA VOICED SOUND MARK
\u{FF9F}: HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
DerivedCoreProperties.txt
に “Grapheme_Extend
” として載っている。この中には spacing mark Mc
が 26個含まれている。(UnicodeData.txt
全体で 401個)
またタグ文字 E0020~E007F
は Cf
に属するが、GE に含まれている。"strongly discouraged" とある。
“grapheme extender” に関する説明は分かりにくい。"extender" だから何かに作用すると思えるが、何にどのように作用するのか説明が見つからない。多分 grapheme base に後ろから作用するのだと思えるが... 作用で生成されたものが Legacy grapheme cluster になるように思えるが、明示的な説明が無い。 → この理解でよい。文献[13]
スタック・オーバーフローに
“What is the difference between ‘combining characters’ and ‘grapheme extenders’ in Unicode?”
の議論がある。何か参考になるかも知れない。
https://stackoverflow.com/questions/21722729/what-is-the-difference-between-combining-characters-and-grapheme-extenders-i
Grapheme base: A character with the property Grapheme_Base, or any standard Korean syllable block.
The set of characters with the Grapheme_Extendproperty and the set of characters with the Grapheme_Base property are disjoint, by definition.
GB := GC - GE # "-" is a subtraction of sets
GB: grapheme base
GC: graphic character
GE: grapheme extender
A legacy grapheme cluster is defined as a base (such as A or カ) followed by zero or more continuing characters. One way to think of this is as a sequence of characters that form a “stack”.
LGC := CRLF | (GB|HAN|RI) (GE)* | .
LGC: legacy grapheme cluster
CRLF: 000D:000A
GB: grapheme base
HAN: a Hangul syllable (or Hangul Jamos)
RI: a pair of regional indicator
GE: grapheme extender
LGC
の定義は “(GE)*
” ではなく、“(NM|JC|SMC)*
” なのであるが、文献[13]の
Table 1b. Combining Character Sequences and Grapheme Clusters
(GE)*
” が正しい。(こちらの方が正確)
Hangul Jamo の中には古い Hangul を構成する部品も含まれている。古い Hangul にはコードポイントが与えられていないので、 Legacy grapheme cluster で構成可能であることを言いたいらしい。
注釈: CRLF
Windows の改行 CRLF
は2文字で1つの編集単位であるから grapheme cluster に含めておく必要がある。
1文字の全ての制御文字もまた同様である。
注釈: regional indicator
コードポイント 1F1E6~1F1FF
は RI 用に A~Z を表す。日本は JP なので RI は 1F1EF:1F1F5
。これで日本の国旗 🇯🇵 が表示される。
An extended grapheme cluster is the same as a legacy grapheme cluster, with the addition of some other characters. The continuing characters are extended to include all spacing combining marks, such as the spacing (but dependent) vowel signs in Indic scripts. For example, this includes U+093F ( ि ) DEVANAGARI VOWEL SIGN I. The extended grapheme clusters should be used in implementations in preference to legacy grapheme clusters, because they provide better results for Indic scripts such as Tamil or Devanagari in which editing by orthographic syllable is typically preferred. For scripts such as Thai, Lao, and certain other Southeast Asian scripts, editing by visual unit is typically preferred, so for those scripts the behavior of extended grapheme clusters is similar to (but not identical to) the behavior of legacy grapheme clusters.
EGC := CRLF | (GB|HAN|RI) (GE|SM)* | .
EGC: extended grapheme cluster
CRLF: 000D:000A
GB: grapheme base
HAN: a Hangul syllable (or Hangul Jamos)
RI: a pair of regional indicator
GE: grapheme extender
SM: spacing mark (Mc)
U+093F
093F
は spacing mark である。母音記号。母音が子音の左に来るのは、左から右に読むからであろうと思ったのであるが、調べてみると左から右に書くらしい。不思議である。
“Legacy grapheme cluster” と “Extended grapheme cluster” の主な違いは、前者が結合文字として(少数の例外を除いて) non-spacing mark のみであるが、後者は spacing mark をも含めるところにある。(より、一般的になっている)
最近(2015) Prepended_Concatenation_Mark が導入された[15]。これを含めると EGC
のシンタックスは
EGC := PCM* (GB|HAN|RI) (GE|SM)*
PCM: prepended concatenation mark
この属性を持つ文字の一覧は PropList.txt にある。
7. 接合子
7.0.1. ゼロ幅接合子/ゼロ幅非接合子
U+200D zero width joiner is intended to produce a more connected rendering of adjacent characters than would otherwise be the case, if possible.
U+200C zero width non-joiner is intended to break both cursive connections and ligatures in rendering.
zero width joiner and zero width non-joiner are format control characters.
Letter 200D Letter
Letter 200C Letter
Letter 200D 200C Letter
Letter 200D 200C 200D Letter
7.0.2. Combining Grapheme Joiner
U+034F combining grapheme joiner (CGJ) is used to affect the collation of adjacent characters for purposes of language-sensitive collation and searching. It is also used to distinguish sequences that would otherwise be canonically equivalent.
“combining” の修飾子は、combining character に属している事を強調したいからか? 修飾子無しの “Grapheme Joiner” なるものが別に存在しないので要らないのではないか? あいるは将来予定されているのか?
また同 Wikipedia には、『文字名称の上では「結合子」となっているが、文字を結合するのではなく、むしろ結合しないことを表す』と書かれている。見かけ上結合しているだけよ... との意味らしい。
このようなものが必要となるのは、複数の文字の組みで(事実上)1文字を表す文字体系が存在するから。(例えばスロバキア語の"CH")
疑問: CGJ は Mn
に属しているから CCS を終了させないと言っている。ならば ZWJ や ZWNJ は終了させるのか?
% grep JOINER UnicodeData.txt
034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;;
200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;;
200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;;
2060;WORD JOINER;Cf;0;BN;;;;;N;;;;;
2D7F;TIFINAGH CONSONANT JOINER;Mn;9;NSM;;;;;N;;;;;
1107F;BRAHMI NUMBER JOINER;Mn;9;NSM;;;;;N;;;;;
11A47;ZANABAZAR SQUARE SUBJOINER;Mn;9;NSM;;;;;N;;;;;
11A99;SOYOMBO SUBJOINER;Mn;9;NSM;;;;;N;;;;;
%
7.0.3. ゼロ幅接合子による表現例
1F468:200D:1F4BB
1F468:200D:1F4BB
の見え方: 👨💻
むしろブラウザが動いているシステムでの見え方と言うべきである。フォントはブラウザではなくシステムの問題だから...
1F468
の意味は “MAN” であり、1F4BB
の意味は “PERSONAL COMPUTER” である。これらは、意味を崩さない範囲で自由にデザインできる。また、この2つから生成される合体図形も、“MAN” with “PERSONAL COMPUTER” の範囲で自由にデザインできる。送られてきたメールに Mac の絵文字が入っていても、送信者が Mac から送った保証はない。
% grep '^(1F468|200D|1F4BB)' UnicodeData.txt
200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;;
1F468;MAN;So;0;ON;;;;;N;;;;;
1F4BB;PERSONAL COMPUTER;So;0;ON;;;;;N;;;;;
%
1F469:200D:2764:200D:1F469
1F469:200D:2764:200D:1F469
の見え方: 👩❤👩
% grep '^(1F469|200D|2764)' UnicodeData.txt
200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;;
2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;;
1F469;WOMAN;So;0;ON;;;;;N;;;;;
%
When an emoji zwj sequence is sent to a system that does not have a corresponding single glyph, the ZWJ characters are ignored and a fallback sequence of separate emoji is displayed.
注1: 接合子が作用する相手の正確な説明が欲しいが... どこにあるか分からない。
8. Appendix
8.1. UTF-8
x in [00000000.00000000.0bbbbbbb] → 0bbbbbbb
x in [00000000.00000bbb.bbbbbbbb] → 110bbbbb,10bbbbbb
x in [00000000.bbbbbbbb.bbbbbbbb] → 1110bbbb,10bbbbbb,10bbbbbb
x in [000bbbbb.bbbbbbbb.bbbbbbbb] → 11110bbb,10bbbbbb,10bbbbbb,10bbbbbb
b
は 0
or 1
in
を評価し、YES ならそこで byte 列を生成し、それを答えとする。
逆(UTF-8 から Unicode の生成)は気を付ける必要がある。
何故なら →
の右は全ての b
の値が許されるわけでは無いから。不正の UTF-8 表現は排除する必要がある。
たとえば
1100000b,10bbbbbb
0bbbbbbb
The definition of UTF-8 prohibits encoding character numbers between U+D800 and U+DFFF, which are reserved for use with the UTF-16 encoding form (as surrogate pairs) and do not directly represent characters.
実際の処理は unsigned integer に変換されることが多い。(UTF-32 に変換したと言ってもよい)
例えばテキストエディタ
https://tools.ietf.org/html/rfc3629
8.2. Surrogate Pair
文献[7] p.124 に説明されている。
簡単に言えば(bit表現で)
uuuuuxxxxxxxxxxxxxxxx → 110110wwwwxxxxxx 110111xxxxxxxxxx
wwww = uuuuu -1
である。(uuuuu
は plane を表している)
注 1101(2)=D(16)
例えば Unicode 10302(16)
は
uuuuu=00001(2)
xxxxxxxxxxxxxxxx=0000001100000010(2)
wwww=0000(2)
110110wwwwxxxxxx=1101100000000000(2)=D800(16)
110111xxxxxxxxxx=1101111100000010(2)=DF02(16)
となる。
9. 文献
http://www.unicode.org/charts/PDF/U0000.pdf
http://www.unicode.org/charts/PDF/U4E00.pdf
http://www.unicode.org/versions/Unicode9.0.0/ch18.pdf
http://www.unicode.org/reports/tr44/#General_Category_Values
http://kodomo.bunka.go.jp/seisaku/bunkashingikai/kokugo/shoiinkai/iinkai_14/pdf/shiryo_3.pdf
http://www.unicode.org/
http://www.unicode.org/versions/Unicode9.0.0/UnicodeStandard-9.0.pdf
http://www.unicode.org/reports/
http://www.unicode.org/charts/
http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
http://www.unicode.org/terminology/term_en_ja.html
http://unicode.org/faq/char_combmark.html
http://www.unicode.org/reports/tr29/
http://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
http://blog.unicode.org/2015/11/new-character-property-for-prepended.html
http://www.unicode.org/press/emoji.html
http://unicode.org/emoji/charts/emoji-zwj-sequences.html
http://www.unicode.org/emoji/charts/full-emoji-list.html
http://www.unicode.org/reports/tr51/