#include #include #include #include #include #include #include #include static void draw_needle(cairo_t *cr, double x, double y, double r, double min_angle, double max_angle, double value) { double angle = min_angle + ((max_angle - min_angle) * value) - 90.0; cairo_move_to(cr, x, y); cairo_set_source_rgb(cr, 0, 0.25, 1.0); cairo_line_to(cr, x + r * cos((M_PI/180.0) * angle), y + r * sin((M_PI/180.0) * angle)); cairo_stroke(cr); } static void draw_face_number(cairo_t *cr, double x, double y, double r, double min_angle, double max_angle, double value, const char *text) { double angle = min_angle + ((max_angle - min_angle) * value) - 95; cairo_set_source_rgb(cr, 1, 1, 1); cairo_move_to(cr, x + r * cos((M_PI/180.0) * angle), y + r * sin((M_PI/180.0) * angle)); cairo_save(cr); cairo_rotate(cr, (M_PI/180.0) * (angle + 95)); cairo_show_text(cr, text); cairo_restore(cr); } static void redraw(cairo_t *cr) { int i; /* * Set up text */ cairo_select_font_face(cr, "Helvetica", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, 24); /* * Paint canvas black */ cairo_set_source_rgb(cr, 0, 0, 0); cairo_paint(cr); /* * Draw two identical circles */ cairo_set_source_rgb(cr, 1, 1, 1); cairo_arc(cr, 208, 240, 192, 0, 360); cairo_stroke(cr); cairo_arc(cr, 816, 240, 192, 0, 360); cairo_stroke(cr); /* * Draw face numbers */ for (i=0; i<=80; i+=10) { char text[4]; snprintf(text, 3, "%02d", i); draw_face_number(cr, 208, 240, 162, 232, 488, i / 80.0, text); } /* * Draw a gauge needle */ draw_needle(cr, 208, 240, 148, 232, 488, 0.0); /* * Draw a tiny boi circle */ cairo_set_source_rgb(cr, 1, 1, 1); cairo_arc(cr, 208, 240, 16, 0, 360); cairo_fill(cr); /* * Draw two smaller circles */ cairo_arc(cr, 442, 368, 64, 0, 360 * (M_PI/180)); cairo_stroke(cr); cairo_arc(cr, 582, 368, 64, 0, 360 * (M_PI/180)); cairo_stroke(cr); /* * Draw a rectangle */ cairo_move_to(cr, 432, 48); cairo_line_to(cr, 592, 48); cairo_line_to(cr, 592, 288); cairo_line_to(cr, 432, 288); cairo_line_to(cr, 432, 48); cairo_set_source_rgb(cr, 0.75, 0, 0); cairo_fill(cr); cairo_move_to(cr, 432, 48); cairo_line_to(cr, 592, 48); cairo_line_to(cr, 592, 288); cairo_line_to(cr, 432, 288); cairo_line_to(cr, 432, 48); cairo_set_source_rgb(cr, 1, 1, 1); cairo_stroke(cr); } int main(int argc, char **argv) { Display *display; Window win; Pixmap buf; GC gc; int screen, x = 1024, y = 480; XGCValues values = { .foreground = 0x000000, .background = 0xffffff, .graphics_exposures = 0 }; cairo_surface_t *sfc; cairo_t *ctx; XEvent e; if ((display = XOpenDisplay(NULL)) == NULL) exit(1); screen = DefaultScreen(display); win = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, x, y, 0, 0, 0); gc = XCreateGC(display, win, GCForeground | GCBackground | GCGraphicsExposures, &values); buf = XCreatePixmap(display, win, x, y, 24); XSelectInput(display, win, ExposureMask | ButtonPressMask | KeyPressMask); XMapWindow(display, win); sfc = cairo_xlib_surface_create(display, buf, DefaultVisual(display, screen), x, y); cairo_xlib_surface_set_size(sfc, x, y); ctx = cairo_create(sfc); redraw(ctx); while (1) { XExposeEvent *expose; XNextEvent(cairo_xlib_surface_get_display(sfc), &e); switch (e.type) { case Expose: expose = (XExposeEvent *)&e; XCopyArea(display, buf, win, gc, expose->x, expose->y, expose->width, expose->height, expose->x, expose->y); break; case ButtonPress: case KeyPress: goto done; default: fprintf(stderr, "Dropping unhandled XEvent.type = %d.\n", e.type); } } done: cairo_destroy(ctx); cairo_surface_destroy(sfc); XCloseDisplay(display); return 0; }