## page was renamed from clear/note/wmdev/2011-08-23 = テキストの描画 = "hello, world."とか表示してみる。 == GC == 何かを描画するには、なにはともあれGC(Graphics Context)が必要になる。ということで作る。 XCreateGC:: グラフィクスコンテキストを作成する {{{ GC XCreateGC(Display *display, Drawable d, unsigned long valuemask, XGCValues *values); }}} * `Drawable`とは描画対象のことで、`Window`か`Pixmap`(バックバッファみたいなやつ) * GCはたくさんの属性を持っているため、特に設定したい属性だけを`valuemask`で指定し、`values`に属性値を渡す ということで何も考えずに作るとこんな感じ。 {{{#!highlight c Display *d; Window w; GC gc = XCreateGC(d, w, 0, NULL); }}} 破棄は`XFreeGC()`で行う。 == 文字列描画 == とりあえず非マルチバイト文字のみ。一番単純なのはこれ。 XDrawString:: 文字列を描画する {{{ int XDrawString(Display *display, Drawable d, GC gc, int x, int y, char *string, int length); }}} これだけでは物足りないのでフォントを設定する。といっても難しくない。 {{{#!highlight c GC gc; /* ... */ XFontStruct *fn; fn = XLoadQueryFont(d, "-adobe-helvetica-medium-r-normal--14-*-*-*-*-*-*-*"); /* XLFD */ XSetFont(d, gc, fn->fid); /* ... */ XFreeFont(d, fn); /* 破棄 */ }}} == hello, world == ということで、ウィンドウの中央に"hello, world."と表示するだけのプログラム。 {{{#!highlight c #include #include #include #include #include #include /* functions */ int event_loop(void); GC initgc(void); void draw(GC gc); /* global variables */ Display *d; Window w; Atom wm_delete_window; XFontStruct *fn; int main(int argc, char **argv) { int status; if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) fputs("warning: locale not supported", stderr); d = XOpenDisplay(NULL); if (!d) { fprintf(stderr, "failed to open display\n"); exit(1); } w = XCreateSimpleWindow( d, DefaultRootWindow(d), 0, 0, 400, 300, 1, BlackPixel(d, 0), WhitePixel(d, 0)); XmbSetWMProperties(d, w, "文字列の描画", NULL, argv, argc, NULL, NULL, NULL); wm_delete_window = XInternAtom(d, "WM_DELETE_WINDOW", False); XSetWMProtocols(d, w, &wm_delete_window, 1); XMapWindow(d, w); XFlush(d); XSelectInput(d, w, ExposureMask | StructureNotifyMask); status = event_loop(); XCloseDisplay(d); return status; } int event_loop(void) { XEvent event; GC gc; if (!(gc = initgc())) { fputs("failed to initialize GC", stderr); return 1; } fn = XLoadQueryFont(d, "-adobe-helvetica-medium-r-normal--14-*-*-*-*-*-*-*"); if (!fn) { fputs("failed to load fn", stderr); } else { XSetFont(d, gc, fn->fid); } for (;;) { XNextEvent(d, &event); switch (event.type) { case Expose: draw(gc); break; case ClientMessage: if ((Atom)event.xclient.data.l[0] == wm_delete_window) XDestroyWindow(d, w); break; case DestroyNotify: return 0; } } XFreeGC(d, gc); XFreeFont(d, fn); } GC initgc(void) { GC gc = XCreateGC(d, w, 0, NULL); return gc; } void draw(GC gc) { char *text = "hello, world."; int len = strlen(text); XWindowAttributes att; int t_width, t_height; int x, y; XGetWindowAttributes(d, w, &att); t_width = XTextWidth(fn, text, len); t_height = fn->ascent + fn->descent; x = (att.width - t_width) / 2; y = (att.height - t_height) / 2; XDrawString(d, w, gc, x, y, text, len); } }}} === 問題点 === * 実はy方向が微妙に中央にならない * イベント処理の構造をもう少し考えておいた方が、多分後々になって幸せになれる * フォントはGC作成時に指定してしまって構わないだろう * マルチバイト文字は表示できない * フォントセットを使い、`Xmb*`系関数で描画する必要がある * アンチエイリアスやスケーラブルフォントを使いたければXftを使う必要がある