元号の組文字を分けて表示させてみた
お久しぶりの方も初めましての方もこんにちは。
CTJ 松江ラボ所属のでぃさんです。
今回は前回のブログに引き続き、改元についてのブログ第 2 弾として組文字に関してお話しをしようと思います。前回の記事をまだ読んでいない方はぜひ第 1 弾もチェックしてみてください!
組文字とは?
組文字とは複数の文字を1文字として表示している文字のことです。
たとえば、㍻ これが平成の組文字になります。Unicode 上では U+337B が割り当てられています。
新元号である令和の組文字は Unicode 上で U+32FF として既に割り当ては決まっているのですが、まだ組文字対応が行われていないため、現状では U+32FF を参照しても令和の組文字は表示されません。
U+32FF を参照した文字が → ㋿ です。
元号対応が行われている場合には元号が正しく表示されますが、未対応の場合には四角が表示されます。
組文字を分割してみた
Unicode では組文字を分割する仕組みがあります。元号対応として組文字が追加された際には、組文字の分割についてもあわせてアップデートされると予想されます。そこで今回は、元号対応がされたときにその変更について確認が行え、個人的に興味が湧いた Unicode 正規化を利用した組文字の分割表示を試してみました。現時点では令和の組文字対応はされていないため、「平成」の組文字を分割した例をご紹介します。
ステップ1:組文字を分割するプログラムを用意する
以下の C++ で記述されたファイルは、テキストを同等な合成、分解形式に変換する Unicode の正規化を利用して、指定した組文字を分割表示するプログラムになります。
/*
* Code based on http://www.nslabs.jp/icu-normalization.rhtml
* Inspired by https://nixeneko.hatenablog.com/entry/2018/04/01/000000
*/
#include <stdio.h>
#include <assert.h>
#include <string>
#include <unicode/normlzr.h>
#include <unicode/schriter.h>
class MyChIter: public UCharCharacterIterator
{
typedef UCharCharacterIterator super;
public:
MyChIter(const UnicodeString& str): super(str.getBuffer(), str.length()),
m_str(str), m_pos(0), m_end(str.length()) { }
virtual ~MyChIter() { }
private:
const UnicodeString m_str;
int m_pos;
const int m_end;
};
// UnicodeString を UTF8String に変換する
static std::string uc2str(UChar32 uc)
{
std::string s;
UnicodeString ustr;
ustr.setTo(uc);
ustr.toUTF8String(s);
return s;
}
int main()
{
// UnicodeString str = "㍻";
UnicodeString str = "\u337b";
// Unicode 正規化を行うことで「U+337B」を「U+5E73」と「U+6210」に分割する
icu::Normalizer norm(MyChIter(str), UNORM_NFKC);
for (UChar32 uc = norm.first(); uc != norm.DONE; uc = norm.next() ) {
// 変換した文字を表示する
std::string s = uc2str(uc);
printf("%s", s.c_str());
}
printf("\n");
return 0;
}
このプログラムの流れを簡単に説明します。
まず、分割したい組文字の指定を行います。今回は㍻(U+337B)を分割する組文字として指定しています。次に、Unicode 正規化を利用することで組文字と対応している文字コードに分解します。今回の例では、㍻(U+337B) を 平 (U+5E73) と 成 (U+6210) に分解しています。そして、UnicodeString 型から UTF8String 型に変換し分解した文字を表示させるという流れです。実際に処理を行っている箇所にはコメントを入れているので確認してみてください。
ステップ2:コンパイルの準備を行う
ステップ 1 のファイルをコンパイルするために、以下の機能を満すパッケージがインストールされている必要があります。今回私は Asianux Server 7 環境で動作確認を行っているため、他のディストリビューションではパッケージ名が異なる場合がありますので注意してください。
-
libicu (使用したバージョン:50.1.2-17.el7.x86_64)
Unicodeと他の文字コードの相互変換を行うなど様々な Unicode に関する機能を実現するためにこのパッケージが必要になります。 -
libicu-devel (使用したバージョン:50.1.2-17.el7.x86_64)
Unicodo の正規化を実現するためには UNORM_NFKC 関数を使用するためにこのパッケージが必要になります。libicu-devel をインストールしていないと、参照先のヘッダーファイルが存在せずエラーとなります。/usr/include/unicode 配下に normlzr.h および schriter.h ファイルがあることを確認してください。 -
gcc-c++ (使用したバージョン:4.8.5-36.el7.1.x86_64)
C++ ファイルをコンパイルするために g++ コマンドを使用するためにこのパッケージが必要になります。
上記のパッケージがない場合は、yum コマンドでインストールを行います。パッケージが全て揃っている場合はステップ 2 の手順は不要ですのでスキップしてください。私の場合は「gcc-c++」と「libiuc-devel」がなかったため以下のコマンドでインストールを行いました。
# yum install gcc-c++ libicu-devel
ステップ3:実行ファイルの作成
準備が整ったら早速コンパイルを行っていきます。以下のコマンドを実行して実行ファイルを作成します。
$ g++ -o nfkc nfkc.cc -licuuc
ls コマンドで確認すると、ファイルが作成されているのが分かります。
$ ls
nfkc nfkc.cc
注意:「-licuuc」オプションをつけないと正しくリンクされず、エラーとなりますので注意が必要です。
ステップ4:動作確認
実行ファイルが作成できたら動作を確認します。
$ ./nfkck
平成
「平成」と表示されているので、期待通りに動いたと言えます。現時点は令和での確認は行なえませんが、令和の組文字が追加されたら「UnicodeString str = "\u337b";」の部分を「UnicodeString str = "\u32ff";」に変更することで確認が出来ます。
それでは、またお会いしましょう(`・ω・')ゝ
以上、でぃさんでした。
参考URL
http://www.nslabs.jp/icu-normalization.rhtml
https://nixeneko.hatenablog.com/entry/2018/04/01/000000
http://userguide.icu-project.org/packaging
https://www.meti.go.jp/policy/it_policy/kaigen/20190405_kaigen_code.pdf
更新履歴
2019年 4月 18日 新規作成