// gcc `pkg-config --cflags --libs cairo` test_template.c -o test_template #include #include #include #include #include typedef struct win { Display *dpy; int scr; Window win; GC gc; int width, height; KeyCode quit_code; } win_t; static void win_init(win_t *win); static void win_deinit(win_t *win); static void win_draw(win_t *win); static void win_handle_events(win_t *win); int main(int argc, char *argv[]) { win_t win; /* do png backend */ png_draw(); /* do xlib backend */ win.dpy = XOpenDisplay(0); if (win.dpy == NULL) { fprintf(stderr, "Failed to open display\n"); return 1; } win_init(&win); win_draw(&win); win_handle_events(&win); win_deinit(&win); XCloseDisplay(win.dpy); return 0; } void draw (cairo_t *cr, int width, int height) { cairo_scale (cr, width, height); cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); /* cairo_set_font_size (cr, 0.3); */ cairo_move_to (cr, 0.05, 0.5); cairo_set_source_rgb (cr, 1, 0, 0); cairo_show_text (cr, "Hello"); } int png_draw () { int width = 400, height = 400; cairo_t *cr; cairo_surface_t *surface; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); cr = cairo_create (surface); draw (cr, width, height); cairo_surface_write_to_png (surface, "test.png"); if (cairo_status (cr)) { printf("Cairo is unhappy: %s\n", cairo_status_to_string (cairo_status (cr))); exit(0); } cairo_surface_destroy (surface); cairo_destroy (cr); return 0; } static void win_draw(win_t *win) { cairo_surface_t *surface; cairo_t *cr; Visual *visual = DefaultVisual(win->dpy, DefaultScreen (win->dpy)); XClearWindow(win->dpy, win->win); surface = cairo_xlib_surface_create (win->dpy, win->win, visual, win->width, win->height); cr = cairo_create(surface); draw (cr, win->width, win->height); if (cairo_status (cr)) { printf("Cairo is unhappy: %s\n", cairo_status_to_string (cairo_status (cr))); exit(0); } cairo_destroy(cr); cairo_surface_destroy (surface); } static void win_init(win_t *win) { Window root; win->width = 400; win->height = 400; root = DefaultRootWindow(win->dpy); win->scr = DefaultScreen(win->dpy); win->win = XCreateSimpleWindow(win->dpy, root, 0, 0, win->width, win->height, 0, BlackPixel(win->dpy, win->scr), BlackPixel(win->dpy, win->scr)); win->quit_code = XKeysymToKeycode(win->dpy, XStringToKeysym("Q")); XSelectInput(win->dpy, win->win, KeyPressMask |StructureNotifyMask |ExposureMask); XMapWindow(win->dpy, win->win); } static void win_deinit(win_t *win) { XDestroyWindow(win->dpy, win->win); } static void win_handle_events(win_t *win) { XEvent xev; while (1) { XNextEvent(win->dpy, &xev); switch(xev.type) { case KeyPress: { XKeyEvent *kev = &xev.xkey; if (kev->keycode == win->quit_code) { return; } } break; case ConfigureNotify: { XConfigureEvent *cev = &xev.xconfigure; win->width = cev->width; win->height = cev->height; } break; case Expose: { XExposeEvent *eev = &xev.xexpose; if (eev->count == 0) win_draw(win); } break; } } }