[2020.12] 古い方法でも動くか確認。
Xでは伝統的に, フォントを XLFD (X Logical Font Description) で選択するようになっていた。フォントはビットマップフォント。この方法は廃れた。
Xに含まれるもう一つの方法は, Xft。ただ、これも開発は低迷している。
Core X11 Font
この方法は、コンパイルは通るが、完全に廃れた。
XLFD の最後の2フィールドで文字セット (Coded Character Set; CCS) を表す。XDrawString*()
に与えるテキストデータは、CCS に応じた値。
xfontsel でマッチするフォントを確認できる。
Fedora 33 だと、今さらビットマップフォントでもないので、インストールされているフォントは非常に限られる。iso8859-1, jisx0208.1983-0, iso10646-1 で, 大きさを揃えることもできない。
C++
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <X11/Xlib.h>
- #include <stdint.h>
-
-
-
-
-
- const char* FONT_NAME_UB =
- "-*-helvetica-bold-o-normal--*-240-*-*-p-*-iso8859-1";
- const char* FONT_NAME_MB =
- "-*-fixed-*-r-normal--*-230-*-*-c-*-jisx0208.1983-0";
- const char* FONT_NAME_UNI =
- "-*-*-medium-r-normal-ja-*-120-*-*-*-*-iso10646-1";
-
- XFontStruct* font_ub = NULL;
- XFontStruct* font_mb = NULL;
- XFontStruct* font_uni = NULL;
- GC gc_ub, gc_mb, gc_uni;
-
- static const char* text_ub = "English";
-
-
- static const XChar2b text_mb[] = {
- {.byte1 = 0x34, .byte2 = 0x41},
- {.byte1 = 0x3b, .byte2 = 0x7a} };
-
-
- static const XChar2b text_uni[] = {
- {.byte1 = 0x00, .byte2 = 0x41},
- {.byte1 = 0x30, .byte2 = 0x42} };
-
-
- void onExposed(const XExposeEvent* e)
- {
- printf("onExposed() enter\n");
- int x, y;
- int i;
-
- x = 10; y = 100;
- for (i = 0; i < 2; i++) {
-
- XDrawString(e->display, e->window, gc_ub, x, y, text_ub,
- strlen(text_ub));
- x += XTextWidth(font_ub, text_ub, strlen(text_ub));
- XDrawString16(e->display, e->window, gc_mb, x, y, text_mb, 2);
- x += XTextWidth16(font_mb, text_mb, 2);
- XDrawString16(e->display, e->window, gc_uni, x, y, text_uni, 2);
- x += XTextWidth16(font_uni, text_uni, 2);
- }
- }
-
- int main()
- {
-
- Display* disp = XOpenDisplay(NULL);
- Window toplevel = XCreateSimpleWindow(disp, RootWindow(disp, 0),
- 400, 200,
- 500, 150, 2,
- BlackPixel(disp, 0),
- WhitePixel(disp, 0));
- XSelectInput(disp, toplevel, ExposureMask | ButtonPressMask);
- XMapWindow(disp, toplevel);
-
-
- font_ub = XLoadQueryFont(disp, FONT_NAME_UB);
- assert(font_ub);
-
- font_mb = XLoadQueryFont(disp, FONT_NAME_MB);
- assert(font_mb);
- printf("min_char_or_byte2 = %d\n", font_mb->min_char_or_byte2);
- printf("max_char_or_byte2 = %d\n", font_mb->max_char_or_byte2);
- printf("min_byte1 = %d\n", font_mb->min_byte1);
- printf("max_byte1 = %d\n", font_mb->max_byte1);
-
- font_uni = XLoadQueryFont(disp, FONT_NAME_UNI);
- assert(font_uni);
-
-
- gc_ub = XCreateGC(disp, toplevel, 0, NULL);
- XSetForeground(disp, gc_ub, BlackPixel(disp, 0));
- XSetFont(disp, gc_ub, font_ub->fid);
-
- gc_mb = XCreateGC(disp, toplevel, 0, NULL);
- XSetForeground(disp, gc_mb, BlackPixel(disp, 0));
- XSetFont(disp, gc_mb, font_mb->fid);
-
- gc_uni = XCreateGC(disp, toplevel, 0, NULL);
- XSetForeground(disp, gc_uni, BlackPixel(disp, 0));
- XSetFont(disp, gc_uni, font_uni->fid);
-
-
- while (true) {
- XEvent ev;
- XNextEvent(disp, &ev);
- if (ev.type == Expose)
- onExposed(&ev.xexpose);
- else if (ev.type == ButtonPress)
- break;
- }
-
- XCloseDisplay(disp);
-
- return 0;
- }
実行結果:
字が小さい。とほほ。
Xft
この方法はまだ現役だが、バグが放置されており、将来は暗い。
特に, 絵文字 Emoji に対応しておらず、逆に絵文字フォントを指定すると落ちる。pango-view コマンドのバックエンドとしてXft を指定した場合も同様に落ちるので、Xft の問題。
このバグ BadLength X error in Xft when trying to render emoji だが、2018年に報告されたバグがまだ修正されていない。
IVS にも未対応. FreeType を直接使えば扱えるようだ (未確認).
C++
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <stdint.h>
- #include <X11/Xlib.h>
- #include <X11/Xft/Xft.h>
-
- XftFont* xftFont = nullptr;
- XftDraw* xftDraw = nullptr;
- XftColor xftColor;
-
- static const char* text_ub = "English";
-
-
-
- static const uint32_t text_uni[] = {
- 0x0041,
- 0x3042,
- 0x845b, 0xe0100,
- 0x845b, 0xe0101,
- 0x1f601,
- 0 };
描画は XftDrawString*()
. UCS-4 または UTF-16 を渡す。
フォントについては, FreeType を利用しており, fc-list コマンドや fc-match コマンドで確認できる。
C++
- void onExposed(const XExposeEvent* e)
- {
- printf("onExposed() enter\n");
- int x, y;
- int i;
-
- x = 10; y = 150;
- for (i = 0; i < 2; i++) {
-
- XftDrawString8(xftDraw, &xftColor, xftFont, x, y,
- (unsigned char*) text_ub, strlen(text_ub));
- XGlyphInfo extents;
- XftTextExtents8(e->display, xftFont,
- (unsigned char*) text_ub, strlen(text_ub), &extents);
- x += extents.width;
-
- XftDrawString32(xftDraw, &xftColor, xftFont, x, y, text_uni, 7);
- XftTextExtents32(e->display, xftFont, text_uni, 7, &extents);
- x += extents.width;
- }
- }
-
- int main()
- {
-
- Display* disp = XOpenDisplay(NULL);
- Window toplevel = XCreateSimpleWindow(disp, RootWindow(disp, 0),
- 400, 200,
- 800, 300, 2,
- BlackPixel(disp, 0),
- WhitePixel(disp, 0));
- XSelectInput(disp, toplevel, ExposureMask | ButtonPressMask);
- XMapWindow(disp, toplevel);
-
-
-
-
-
- xftFont = XftFontOpenName(disp,
- 0,
- "Noto Sans CJK JP:pixelsize=36:style=DemiLight" );
- assert(xftFont);
- Colormap cmap = DefaultColormap(disp, 0);
- Bool r = XftColorAllocName(disp, DefaultVisual(disp, 0), cmap, "blue",
- &xftColor);
- assert(r);
- xftDraw = XftDrawCreate(disp,
- toplevel,
- DefaultVisual(disp, 0),
- cmap );
- assert(xftDraw);
-
-
- while (true) {
- XEvent ev;
- XNextEvent(disp, &ev);
- if (ev.type == Expose)
- onExposed(&ev.xexpose);
- else if (ev.type == ButtonPress)
- break;
- }
-
- XftFontClose(disp, xftFont);
- XftDrawDestroy(xftDraw);
-
-
- XCloseDisplay(disp);
-
- return 0;
- }
実行結果:
豆腐になる。落ちるよりはよい。