diff --git a/examples/cluster.c b/examples/cluster.c index 18bc7d3..c2f5923 100644 --- a/examples/cluster.c +++ b/examples/cluster.c @@ -50,20 +50,38 @@ static void draw_face_number(cairo_t *cr, cairo_save(cr); cairo_rotate(cr, angle + 1.658); cairo_show_text(cr, text); + cairo_stroke(cr); cairo_restore(cr); } +static void draw_tachometer_needle(cairo_t *cr, + double x, + double y, + double r, + double rpm) { + if (rpm > 8000) { + rpm = 8000; + } + + draw_needle(cr, x, y, 0.77 * r, + 232 * (M_PI/180), + 488 * (M_PI/180), + rpm / 8000); + + /* + * Draw a tiny boi circle + */ + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_arc(cr, x, y, 0.08 * r, 0, 2*M_PI); + cairo_fill(cr); +} + static void draw_tachometer(cairo_t *cr, double x, double y, - double r, - double rpm) { + double r) { int i; - if (rpm > 8000) { - rpm = 8000; - } - cairo_select_font_face(cr, "Helvetica", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); @@ -89,21 +107,6 @@ static void draw_tachometer(cairo_t *cr, i / 80.0, text); } - - /* - * Draw a gauge needle - */ - draw_needle(cr, x, y, 0.77 * r, - 232 * (M_PI/180), - 488 * (M_PI/180), - rpm / 8000); - - /* - * Draw a tiny boi circle - */ - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_arc(cr, x, y, 0.08 * r, 0, 2*M_PI); - cairo_fill(cr); } static void draw_speedometer(cairo_t *cr, @@ -152,7 +155,55 @@ static void draw_mfd(cairo_t *cr, cairo_stroke(cr); } -static void draw_gauge_cluster(cairo_t *cr, +static void draw_gauge_cluster_bg(Pixmap buf, + Display *display, + int screen, + double width, + double height) { + cairo_surface_t *sfc; + cairo_t *cr; + + sfc = cairo_xlib_surface_create(display, buf, DefaultVisual(display, screen), width, height); + cairo_xlib_surface_set_size(sfc, width, height); + + cr = cairo_create(sfc); + + /* + * Paint canvas black + */ + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_paint(cr); + + draw_tachometer(cr, + width * 0.2, + height * 0.5, + height * 0.4); + + draw_speedometer(cr, + width * 0.8, + height * 0.5, + height * 0.4); + + draw_thermometer(cr, + width * 0.43, + height * 0.76, + height * 0.13); + + draw_fuel_gauge(cr, + width * 0.57, + height * 0.76, + height * 0.13); + + draw_mfd(cr, + width * 0.42, + height * 0.1, + width * 0.16, + height * 0.5); + + cairo_destroy(cr); +} + +static void update_gauge_cluster(cairo_t *cr, struct can_frame *frame, double x, double y, @@ -162,46 +213,21 @@ static void draw_gauge_cluster(cairo_t *cr, if (frame->can_id == 0x280) { rpm = 0.25 * (double)(frame->data[2] | (frame->data[3] << 8)); + } else { + return; } - /* - * Paint canvas black - */ - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_paint(cr); - - draw_tachometer(cr, - x + width * 0.2, - y + height * 0.5, - height * 0.4, - rpm); - - draw_speedometer(cr, - x + width * 0.8, - y + height * 0.5, - height * 0.4); - - draw_thermometer(cr, - x + width * 0.43, - y + height * 0.76, - height * 0.13); - - draw_fuel_gauge(cr, - x + width * 0.57, - y + height * 0.76, - height * 0.13); - - draw_mfd(cr, - x + width * 0.42, - y + height * 0.1, - width * 0.16, - height * 0.5); + draw_tachometer_needle(cr, + x + width * 0.2, + y + height * 0.5, + height * 0.4, + rpm); } int main(int argc, char **argv) { Display *display; Window win; - Pixmap buf; + Pixmap bg; GC gc; fd_set rfds, rready; @@ -230,18 +256,29 @@ int main(int argc, char **argv) { fd2 = ConnectionNumber(display); screen = DefaultScreen(display); - win = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, width, height, 0, 0, 0); - gc = XCreateGC(display, win, GCForeground | GCBackground | GCGraphicsExposures, &values); - buf = XCreatePixmap(display, win, width, height, 24); + win = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, width, height, 0, 0, 0); + gc = XCreateGC(display, win, GCForeground | GCBackground | GCGraphicsExposures, &values); + bg = XCreatePixmap(display, win, width, height, 24); + + /* + * Draw the background layer + */ + draw_gauge_cluster_bg(bg, display, screen, width, height); XSelectInput(display, win, ExposureMask | ButtonPressMask | KeyPressMask); XMapWindow(display, win); - sfc = cairo_xlib_surface_create(display, buf, DefaultVisual(display, screen), width, height); + /* + * Set up the foreground surface + */ + sfc = cairo_xlib_surface_create(display, win, DefaultVisual(display, screen), width, height); cairo_xlib_surface_set_size(sfc, width, height); cr = cairo_create(sfc); + /* + * Set up file descriptors to monitor + */ FD_ZERO(&rfds); FD_SET(fd, &rfds); @@ -259,7 +296,7 @@ int main(int argc, char **argv) { case Expose: fprintf(stderr, "Event %d\n", e.type); - XCopyArea(display, buf, win, gc, + XCopyArea(display, bg, win, gc, e.xexpose.x, e.xexpose.y, e.xexpose.width, @@ -288,11 +325,14 @@ int main(int argc, char **argv) { struct can_frame frame; hexagram_can_if_read(can_if, &frame); - draw_gauge_cluster(cr, &frame, 0, 0, width, height); - XCopyArea(display, buf, win, gc, 0, 0, - width, height, - 0, 0); + if (frame.can_id == 0x280) { + XCopyArea(display, bg, win, gc, 0, 0, + width, height, + 0, 0); + + update_gauge_cluster(cr, &frame, 0, 0, width, height); + } } }