hexagram/src/status.c
XANTRONIX Development 1bda9eda26 Port Python to C
2024-01-14 22:32:46 -05:00

242 lines
7 KiB
C

#include <stdlib.h>
#include <string.h>
#include <hexagram/status.h>
#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; i<STATUS_ICON_COUNT; i++) {
hexagram_icon *icon = &box->icons[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; i<STATUS_ICON_COUNT; i++) {
if (hexagram_icon_init(&box->icons[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; i<STATUS_ICON_COUNT; i++) {
hexagram_icon_cleanup(&box->icons[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;
}