(2005.5.15 新規作成)
m17n libraryは、オープンソース (LGPL 2.1) の、多言語ライブラリ。2018年2月にリリースされた m17n library v1.8.0 が最新。
メジャーなところでは, Emacs が m17n ライブラリを利用している。Emacs 27 から, m17n-flt の HarfBuzz への置き換えが始まっている。
以下サンプルのコンパイルには, Fedora 33 だと, m17n-lib-devel パッケージをインストールする。
タイ語とクメール文字を表示してみる。ついでに絵文字なども。
C++
- const uint16_t data[] = {
- 0x3042,
- 0x4e9c,
- 0x0E19, 0x0E49, 0x0E33,
- 0x1787,
- 0x17BC,
- 0x1793,
- 0xD83D, 0xDE01,
- 0x0041,
- 0x845b, 0xdb40, 0xdd00,
- 0x845b, 0xdb40, 0xdd01,
- 0x0031,
- 0};
main()
関数。
m17nライブラリを使う場合、最初にライブラリを初期化する。m17nライブラリでエラーが発生した場合は、グローバル変数 merror_code
が設定される。
C++
- int main(int argc, char* argv[])
- {
- Arg args[1];
- Widget toplevel, canvas;
-
- XtSetLanguageProc(NULL, NULL, NULL);
- XtSetArg(args[0], XtNtitle, "Unicodeテキストの表示");
- toplevel = XtAppInitialize(&app, "view", NULL, 0, &argc, argv, NULL, args,
- 1);
-
-
- M17N_INIT();
- if (merror_code != MERROR_NONE) {
- printf("Fail to initialize the m17n library.\n");
- return 1;
- }
m17nでは、スクリプトごとにフォントを用意して、それらでフォントセットを作る。スクリプトは、例えば次のものがある。Unicode Character Database (UCD) の Scripts.txt
の名前を使う。
スクリプトの例
スクリプト | 説明
|
hiragana | ひらがな. 3041..3096, 309D..309E, ほか
|
katakana | カタカナ。半角カタカナを含む。30A1..30FA, ほか
|
han | 漢字。互換漢字を含む。
|
スクリプトごとのデフォルトフォント, そのスクリプトを含む文字集合 (CCS) との対応は, /usr/share/m17n/default.fst
ファイル (m17n-db-extras パッケージ) を見るといい。
ここでは、タイ語用のフォントと日本語用のフォントを用意する。フォントを生成するには、フォント名を指定する方法 mfont_parse_name()
と、mfont_put_prop()でファミリー名などフォントの要素を指定する方法がある。
C++
-
- MFont* thai_font = mfont_parse_name("Droid Sans", Mfontconfig);
- MFont* ja_font = mfont_parse_name("Noto Serif CJK JP", Mfontconfig);
- if (!thai_font || !ja_font) {
- printf("Fail to create font.\n");
- return 1;
- }
-
-
- MFontset* fs = mfontset_copy(mfontset(NULL), "my_fontset");
- mfontset_modify_entry(fs, msymbol("thai"), Mnil, Mnil,
- thai_font, msymbol("thai-norasi"), 0);
- mfontset_modify_entry(fs, msymbol("hiragana"), Mnil, Mnil,
- ja_font, Mnil, 0);
- mfontset_modify_entry(fs, msymbol("han"), Mnil, Mnil,
- ja_font, Mnil, 0);
フォントが生成できたら、フォントセットを修正する。mfontset_copy()
でデフォルトのフォントセットをコピーして、それを修正するのがいいと思う。
mfontset_modify_entry()
は、ヘルプの説明(引数の順序)が間違っている。正しくは次のとおり。scriptとlayouter_nameが重要。
int mfontset_modify_entry (
MFontset *fontset,
MSymbol script,
MSymbol language,
MSymbol charset,
MFont *spec,
MSymbol layouter_name,
int how);
m17nライブラリでのテキストは, M-text と呼ぶ。
C++
-
- MPlist* param = mplist();
- MFace* face = mface();
- mface_put_prop(face, Mfontset, fs);
- mface_put_prop(face, Msize, (void*) 450);
- m17n_object_unref(fs); fs = nullptr;
- mplist_put(param, Mwidget, toplevel);
- mplist_put(param, Mface, face);
- m17n_object_unref(face); face = nullptr;
-
- frame = mframe(param);
- m17n_object_unref(param); param = nullptr;
-
-
- mt = mtext_from_data(data, 18,
- MTEXT_FORMAT_UTF_16LE);
- if (!mt) {
- printf("Fail to create M-text object.\n");
- return 1;
- }
-
- canvas = XtVaCreateManagedWidget("canvas", formWidgetClass, toplevel,
- XtNwidth, 500,
- XtNheight, 200, NULL);
- XtAddEventHandler(canvas, ExposureMask, False, on_exposed, NULL);
-
- XtRealizeWidget(toplevel);
-
-
- Atom atom = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", False);
- XSetWMProtocols(XtDisplay(toplevel), XtWindow(toplevel), &atom, 1);
- XtAddEventHandler(toplevel, NoEventMask, True, onCloseClicked, NULL);
-
- XtAppMainLoop(app);
-
- mfont_close(thai_font);
- mfont_close(ja_font);
- m17n_object_unref(frame);
- m17n_object_unref(mt);
-
- M17N_FINI();
- printf("Finished.\n");
-
- return 0;
- }
イベントハンドラを用意。
C++
- #include <stdint.h>
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Shell.h>
- #include <X11/Xaw/Form.h>
- #include <m17n-gui.h>
- #include <m17n-misc.h>
-
- MFrame* frame;
- MText* mt;
- XtAppContext app;
-
- static void on_exposed(Widget w, void* closure, XEvent* event, Boolean* cont)
- {
- int r = mdraw_image_text(frame, (MDrawWindow) XtWindow(w),
- 30, 100, mt, 0, 100);
- if (r != MERROR_NONE) {
- printf("%d\n", merror_code);
- exit(1);
- }
- }
-
- static void onCloseClicked(Widget w, void* closure, XEvent* event,
- Boolean* cont)
- {
- printf("onCloseClicked() enter.\n");
-
- XtAppSetExitFlag(app);
- }
これをコンパイルして、実行すると、次のようになる。
gcc -Wall m17n.cc `pkg-config --cflags --libs m17n-core m17n-gui` -lXaw -lXt -lX11 -lstdc++
IVS には対応していない。絵文字は OK. Fedora 33 で実行すると, サロゲートペアがある場合に, 豆腐が発生する。UTF-16 の処理が不味いようだが, 回避方法はは不明。