m17n libraryを使う

(2005.5.15 新規作成)

m17n libraryは、オープンソースの、多言語ライブラリ。

タイ語とクメール文字を表示してみる。

  7| #include <X11/Intrinsic.h>
  8| #include <X11/StringDefs.h>
  9| #include <X11/Shell.h>
 10| #include <X11/Xaw/Form.h>
 11| #include <m17n-gui.h>
 12| #include <m17n-misc.h>
 13| 
 14| MFrame* frame;
 15| MText* mt;
 16| 
 17| void on_exposed(Widget w, void* closure, XEvent* event, Boolean* cont) {
 18|     int r = mdraw_image_text(frame, (MDrawWindow) XtWindow(w),
 19|                              30, 100, mt, 0, 100);
 20|     if (r != MERROR_NONE) {
 21|         printf("%d\n", merror_code);
 22|         exit(1);
 23|     }
 24| }
 25| 
 26| const unsigned short data[] = {
 27|     0x3042, // あ
 28|     0x4e9c, // 亜
 29|     0x0E19,
 30|     0x0E49,
 31|     0x0E33,
 32|     0x1787,
 33|     0x17BC,
 34|     0x1793,
 35|     0};
 45| int main(int argc, char* argv[]) {
 46|     XtAppContext app;
 47|     Arg args[1];
 48|     Widget top_widget, canvas;
 49| 
 50|     XtSetLanguageProc(NULL, NULL, NULL);
 51|     XtSetArg(args[0], XtNtitle, "Unicodeテキストの表示");
 52|     top_widget = XtAppInitialize(&app, "view", NULL, 0, &argc, argv, NULL, args, 1);

m17nライブラリを使う場合、最初にライブラリを初期化する。m17nライブラリでエラーが発生した場合は、グローバル変数merror_codeが設定される。

 55|     M17N_INIT();
 56|     if (merror_code != MERROR_NONE) {
 57|         printf("Fail to initialize the m17n library.\n");
 58|         return 1;
 59|     }

m17nでは、スクリプトごとにフォントを用意して、それらでフォントセットを作る。スクリプトは、例えば次のものがある。Scripts.txtの名前を使う。

スクリプトの例
スクリプト説明
hiraganaひらがな
katakanaカタカナ。半角カタカナを含む。
han漢字。互換漢字を含む。

デフォルトのスクリプトとフォントとの対応は、m17n-db/default.fstを見るといい。

ここでは、タイ語用のフォントと日本語用のフォントを用意する。フォントを生成するには、フォント名を指定する方法と、mfont_put_prop()でファミリー名などフォントの要素を指定する方法がある。

 62|     MFont* thai_font = mfont_parse_name("Microsoft Sans Serif", Mfontconfig);
 63|     MFont* ja_font = mfont_parse_name("Kochi Mincho", Mfontconfig);
 64|     if (!thai_font || !ja_font) {
 65|         printf("Fail to create font.\n");
 66|         return 1;
 67|     }
 68|     // mfont_put_prop(thai_font, Mfamily, msymbol("norasi"));  違うフォントになる。

フォントが生成できたら、フォントセットを修正する。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);
 70|     MFontset* fs = mfontset_copy(mfontset(NULL), "my_fontset");
 71|     mfontset_modify_entry(fs, msymbol("thai"), Mnil, Mnil,
 72|                           thai_font, msymbol("thai-norasi"), 0);
 73|     mfontset_modify_entry(fs, msymbol("hiragana"), Mnil, Mnil,
 74|                           ja_font, Mnil, 0);
 75|     mfontset_modify_entry(fs, msymbol("han"), Mnil, Mnil,
 76|                           ja_font, Mnil, 0);
 77| 
 78|     // MFrameオブジェクトは、グラフィックデバイスに対応する。
 79|     MPlist* param = mplist();
 80|     MFace* face = mface();
 81|     mface_put_prop(face, Mfontset, fs);
 82|     mface_put_prop(face, Msize, (void*) 500);
 83|     mplist_put(param, Mwidget, top_widget);
 84|     mplist_put(param, Mface, face);
 85| 
 86|     frame = mframe(param);
 87| 
 88|     m17n_object_unref(param);
 89|     m17n_object_unref(face);
 90| 
 91|     // M-textを生成する
 92|     mt = mtext_from_data(data, 8, MTEXT_FORMAT_UTF_16LE);
 93|     if (!mt) {
 94|         printf("Fail to create M-text object.\n");
 95|         return 1;
 96|     }
 97| 
 98|     canvas = XtVaCreateManagedWidget("canvas", formWidgetClass, top_widget,
 99|                             XtNwidth, 300,
100|                             XtNheight, 200, NULL);
101|     XtAddEventHandler(canvas, ExposureMask, False, on_exposed, NULL);
102| 
103|     XtRealizeWidget(top_widget);
104|     XtAppMainLoop(app);
105| 
106|     return 0;
107| }

これをコンパイルして、実行すると、次のようになる。