X11的绘图和输出文字功能不仅使用麻烦,而且效果很差,因此建议使用第三方图形库实现绘图和输出文字功能。cairo是GTK2和GTK3使用的图形库,支持C语言,也可配合X11使用,使用非常简单。但是cairo的文字输出只是演示用途,基本没法用,输出文字一般使用pango这种文字渲染库。
ubuntu配置开发环境的命令:
sudo apt install build-essential libx11-dev libcairo2-dev libpango1.0-dev
编译的命令:
gcc -o xdrawstr xdrawstr.c -lX11 `pkg-config --cflags --libs pangocairo`
xdrawstr.c源代码:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xlocale.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <pango/pangocairo.h>
int main(int argc, char **argv)
{
Display *dpy;
Window w;
int i;
GC gc;
XEvent xe;
int width = 300;
int height = 200;
cairo_surface_t *surface;
PangoFontDescription *font_description;
dpy = XOpenDisplay(NULL);
w = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 50, 50, width, height, 5,
BlackPixel(dpy, 0), WhitePixel(dpy, 0));
surface = cairo_xlib_surface_create(
dpy, w, DefaultVisual(dpy, DefaultScreen(dpy)),
width, height);
font_description = pango_font_description_new();
pango_font_description_set_family(font_description, "sans-serif");
pango_font_description_set_weight (font_description, PANGO_WEIGHT_BOLD);
pango_font_description_set_absolute_size(font_description, 16 * PANGO_SCALE);
XSelectInput(dpy, w, ExposureMask|StructureNotifyMask|
KeyPressMask|ButtonPressMask);
XMapWindow(dpy, w);
XFlush(dpy);
while (True)
{
XNextEvent(dpy, &xe);
switch (xe.type) {
case Expose:
if (1)
{
cairo_t *cr = cairo_create(surface);
PangoLayout *layout = pango_cairo_create_layout(cr);
pango_layout_set_font_description(layout, font_description);
pango_layout_set_text(layout, "你好,世界!", -1);
cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
cairo_move_to(cr, 10.0, 50.0);
pango_cairo_show_layout(cr, layout);
g_object_unref(layout);
cairo_destroy(cr);
}
break;
case ConfigureNotify:
if (1)
{
XConfigureEvent *ce = (XConfigureEvent *)&xe;
width = ce->width;
height = ce->height;
cairo_xlib_surface_set_size(surface, width, height);
}
break;
case KeyPress:
break;
case ButtonPress:
if (1)
{
XButtonEvent *be = (XButtonEvent *)&xe;
if (be->button == Button3)
exit(0);
}
break;
default:
break;
}
}
return 0;
}