#include #include #include #define STATUS_ICON_COUNT 14 #define STATUS_ICON_WIDTH 48 #define STATUS_ICON_HEIGHT 48 static hexagram_icon icons[STATUS_ICON_COUNT] = { { .id = HEXAGRAM_STATUS_SEATBELT, .name = "belt", .style_format = "path {fill: %1$s}", .red = HEXAGRAM_STATUS_SEATBELT_UNFASTENED }, { .id = HEXAGRAM_STATUS_PARKING_BEAM, .name = "beams-parking", .style_format = "path {stroke: %1$s; stroke-width: 12}", .yellow = HEXAGRAM_STATUS_PARKING_BEAM_ON, .red = HEXAGRAM_STATUS_PARKING_BEAM_FAULT }, { .id = HEXAGRAM_STATUS_LOW_BEAM, .name = "beams-low", .style_format = "path {fill: %1$s; stroke: %1$s}", .green = HEXAGRAM_STATUS_LOW_BEAM_ON, .red = HEXAGRAM_STATUS_LOW_BEAM_FAULT }, { .id = HEXAGRAM_STATUS_HIGH_BEAM, .name = "beams-high", .style_format = "path {fill: %1$s; stroke: %1$s}", .blue = HEXAGRAM_STATUS_HIGH_BEAM_ON, .red = HEXAGRAM_STATUS_HIGH_BEAM_FAULT }, { .id = HEXAGRAM_STATUS_FOG_BEAM, .name = "beams-fog", .style_format = "#g9 path {fill: %1$s} #g5 path {stroke: %1$s}", .green = HEXAGRAM_STATUS_FOG_BEAM_ON, .red = HEXAGRAM_STATUS_FOG_BEAM_FAULT }, { .id = HEXAGRAM_STATUS_STABILITY_CONTROL, .name = "stability", .style_format = "#path9, #path8, #path7, #path6, #path5 {fill: %1$s} #path10 {stroke: %1$s}", .orange = HEXAGRAM_STATUS_STABILITY_CONTROL_OFF, .red = HEXAGRAM_STATUS_STABILITY_CONTROL_FAULT }, { .id = HEXAGRAM_STATUS_LANE_ASSIST, .name = "lane-departure", .style_format = "path {stroke: %1$s; stroke-width: 8}", .orange = HEXAGRAM_STATUS_LANE_ASSIST_OFF, .red = HEXAGRAM_STATUS_LANE_ASSIST_FAULT }, { .id = HEXAGRAM_STATUS_PARKING_BRAKE, .name = "parking", .style_format = "#path6, #path5 {stroke: %1$s} circle {stroke: %1$s} #path7 {fill: %1$s}", .red = HEXAGRAM_STATUS_PARKING_BRAKE_ON }, { .id = HEXAGRAM_STATUS_FUEL, .name = "fuel", .style_format = "#g9 * {stroke: %1$s} #path9 {fill: %1$s}", .orange = HEXAGRAM_STATUS_FUEL_LOW, .red = HEXAGRAM_STATUS_FUEL_FAULT }, { .id = HEXAGRAM_STATUS_WIPER_WASHER, .name = "wiper-washer", .style_format = "rect,path,circle{stroke:%1$s;}", .orange = HEXAGRAM_STATUS_WIPER_WASHER_LOW, .red = HEXAGRAM_STATUS_WIPER_WASHER_FAULT }, { .id = HEXAGRAM_STATUS_COOLANT, .name = "coolant", .style_format = "path, circle, rect {fill: %1$s} #g9 path {stroke: %1$s}", .orange = HEXAGRAM_STATUS_COOLANT_LOW, .red = HEXAGRAM_STATUS_COOLANT_OVERHEAT }, { .id = HEXAGRAM_STATUS_OIL, .name = "oil", .style_format = "path {fill: %1$s; stroke: %1$s}", .orange = HEXAGRAM_STATUS_OIL_LOW, .red = HEXAGRAM_STATUS_OIL_OVERHEAT }, { .id = HEXAGRAM_STATUS_TPMS, .name = "tpms", .style_format = "path, circle {fill: %1$s}", .orange = HEXAGRAM_STATUS_TPMS_WARNING, .red = HEXAGRAM_STATUS_TPMS_FAULT }, { .id = HEXAGRAM_STATUS_COLLISION, .name = "collision", .style_format = "path {stroke-width: 10px; stroke: %$1s}", .red = HEXAGRAM_STATUS_COLLISION_DETECTED } }; static int update(hexagram_status_icon_box *box) { cairo_t *cr; double x, y; size_t i; if ((cr = cairo_create(box->surface)) == NULL) { goto error_cairo_create; } cairo_set_source_rgba(cr, 0, 0, 0, 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_rectangle(cr, 0, 0, box->width, box->height); cairo_fill(cr); x = 0; y = box->height - STATUS_ICON_HEIGHT; for (i=0; iicons[i]; int status = box->state[icon->id]; if (status && hexagram_icon_drawable(icon, status)) { if (hexagram_icon_draw(icon, cr, x, y, status) < 0) { goto error_icon_draw; } } x += STATUS_ICON_WIDTH; if (x >= box->width) { x = 0; y -= STATUS_ICON_HEIGHT; } } cairo_destroy(cr); return 0; error_icon_draw: cairo_destroy(cr); error_cairo_create: return -1; } static int draw_fg(hexagram_gauge *gauge, cairo_t *cr) { hexagram_status_icon_box *box = (hexagram_status_icon_box *)gauge; if (box->dirty) { if (update(box) < 0) { goto error_update; } box->dirty = 0; } cairo_set_source_surface(cr, box->surface, gauge->x, gauge->y); cairo_rectangle(cr, gauge->x, gauge->y, box->width, box->height); cairo_fill(cr); return 0; error_update: return -1; } int hexagram_status_icon_box_init(hexagram_status_icon_box *box, double x, double y, double width, double height) { size_t i; box->gauge.x = x; box->gauge.y = y; box->gauge.draw_bg = NULL; box->gauge.draw_fg = draw_fg; box->width = width; box->height = height; box->icons = icons; box->dirty = 0; memset(&box->state, '\0', sizeof(box->state)); for (i=0; iicons[i], STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT) < 0) { goto error_icon_init; } } if ((box->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, box->width, box->height)) == NULL) { goto error_cairo_image_surface_create; } return 0; error_cairo_image_surface_create: error_icon_init: do { hexagram_icon_cleanup(&box->icons[i]); } while (--i); return -1; } void hexagram_status_icon_box_cleanup(hexagram_status_icon_box *box) { size_t i; cairo_surface_destroy(box->surface); for (i=0; iicons[i]); } free(box->icons); return; } void hexagram_status_icon_set(hexagram_status_icon_box *box, hexagram_status_type type, int status) { if (type < 0 || type >= HEXAGRAM_STATUS_COUNT) { return; } box->dirty = 1; box->state[type] = status; }