2019-05-25 18:19:56 -05:00
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <cairo.h>
|
|
|
|
#include <cairo-xlib.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2019-05-25 21:30:31 -05:00
|
|
|
#include <math.h>
|
2019-05-25 18:19:56 -05:00
|
|
|
|
2019-05-25 22:08:26 -05:00
|
|
|
static void draw_needle(cairo_t *cr,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
double r,
|
|
|
|
double min_angle,
|
|
|
|
double max_angle,
|
|
|
|
double value) {
|
2019-05-26 11:18:31 -05:00
|
|
|
double angle = min_angle + ((max_angle - min_angle) * value) - (M_PI/2);
|
2019-05-25 22:08:26 -05:00
|
|
|
|
|
|
|
cairo_move_to(cr, x, y);
|
|
|
|
|
2019-05-25 22:11:26 -05:00
|
|
|
cairo_set_source_rgb(cr, 0, 0.25, 1.0);
|
|
|
|
|
2019-05-25 22:08:26 -05:00
|
|
|
cairo_line_to(cr,
|
2019-05-26 11:18:31 -05:00
|
|
|
x + r * cos(angle),
|
|
|
|
y + r * sin(angle));
|
2019-05-25 22:08:26 -05:00
|
|
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
}
|
|
|
|
|
2019-05-25 22:49:59 -05:00
|
|
|
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) {
|
2019-05-26 11:21:06 -05:00
|
|
|
double angle = min_angle + ((max_angle - min_angle) * value) - 1.658;
|
2019-05-25 22:49:59 -05:00
|
|
|
|
|
|
|
cairo_set_source_rgb(cr, 1, 1, 1);
|
|
|
|
|
|
|
|
cairo_move_to(cr,
|
2019-05-26 11:21:06 -05:00
|
|
|
x + r * cos(angle),
|
|
|
|
y + r * sin(angle));
|
2019-05-25 22:49:59 -05:00
|
|
|
|
|
|
|
cairo_save(cr);
|
2019-05-26 11:21:06 -05:00
|
|
|
cairo_rotate(cr, angle + 1.658);
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_show_text(cr, text);
|
|
|
|
cairo_restore(cr);
|
|
|
|
}
|
|
|
|
|
2019-05-26 10:31:43 -05:00
|
|
|
static void draw_tachometer(cairo_t *cr,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
double r) {
|
2019-05-25 22:49:59 -05:00
|
|
|
int i;
|
|
|
|
|
2019-05-26 10:38:24 -05:00
|
|
|
cairo_select_font_face(cr, "Helvetica",
|
|
|
|
CAIRO_FONT_SLANT_NORMAL,
|
|
|
|
CAIRO_FONT_WEIGHT_NORMAL);
|
|
|
|
|
2019-05-26 16:31:05 -05:00
|
|
|
cairo_set_font_size(cr, r * 0.125);
|
2019-05-26 10:38:24 -05:00
|
|
|
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_set_source_rgb(cr, 1, 1, 1);
|
2019-05-26 11:02:17 -05:00
|
|
|
cairo_arc(cr, x, y, r, 0, 2*M_PI);
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_stroke(cr);
|
|
|
|
|
|
|
|
/*
|
2019-05-26 10:05:46 -05:00
|
|
|
* Draw face numbers
|
2019-05-25 22:49:59 -05:00
|
|
|
*/
|
|
|
|
for (i=0; i<=80; i+=10) {
|
|
|
|
char text[4];
|
|
|
|
|
|
|
|
snprintf(text, 3, "%02d", i);
|
2019-05-26 11:21:06 -05:00
|
|
|
|
|
|
|
draw_face_number(cr, x, y,
|
|
|
|
0.85 * r,
|
|
|
|
232 * (M_PI/180),
|
|
|
|
488 * (M_PI/180),
|
|
|
|
i / 80.0,
|
|
|
|
text);
|
2019-05-25 22:49:59 -05:00
|
|
|
}
|
2019-05-25 18:19:56 -05:00
|
|
|
|
2019-05-25 22:08:26 -05:00
|
|
|
/*
|
|
|
|
* Draw a gauge needle
|
|
|
|
*/
|
2019-05-26 17:31:26 -05:00
|
|
|
draw_needle(cr, x, y, 0.77 * r,
|
|
|
|
232 * (M_PI/180),
|
|
|
|
488 * (M_PI/180), 0.0);
|
2019-05-25 22:08:26 -05:00
|
|
|
|
|
|
|
/*
|
2019-05-26 10:05:46 -05:00
|
|
|
* Draw a tiny boi circle
|
2019-05-25 22:08:26 -05:00
|
|
|
*/
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_set_source_rgb(cr, 1, 1, 1);
|
2019-05-26 11:01:44 -05:00
|
|
|
cairo_arc(cr, x, y, 0.08 * r, 0, 2*M_PI);
|
2019-05-26 10:05:46 -05:00
|
|
|
cairo_fill(cr);
|
2019-05-26 10:08:20 -05:00
|
|
|
}
|
|
|
|
|
2019-05-26 10:32:59 -05:00
|
|
|
static void draw_speedometer(cairo_t *cr,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
double r) {
|
2019-05-26 11:01:44 -05:00
|
|
|
cairo_arc(cr, x, y, r, 0, 2*M_PI);
|
2019-05-26 10:08:20 -05:00
|
|
|
cairo_stroke(cr);
|
|
|
|
}
|
|
|
|
|
2019-05-26 10:33:58 -05:00
|
|
|
static void draw_thermometer(cairo_t *cr,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
double r) {
|
2019-05-26 11:01:44 -05:00
|
|
|
cairo_arc(cr, x, y, r, 0, 2*M_PI);
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_stroke(cr);
|
2019-05-26 10:13:42 -05:00
|
|
|
}
|
2019-05-25 18:19:56 -05:00
|
|
|
|
2019-05-26 10:37:31 -05:00
|
|
|
static void draw_fuel_gauge(cairo_t *cr,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
double r) {
|
2019-05-26 11:01:44 -05:00
|
|
|
cairo_arc(cr, x, y, r, 0, 2*M_PI);
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_stroke(cr);
|
2019-05-26 10:13:42 -05:00
|
|
|
}
|
2019-05-25 18:19:56 -05:00
|
|
|
|
2019-05-26 10:23:24 -05:00
|
|
|
static void draw_mfd(cairo_t *cr,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
double width,
|
|
|
|
double height) {
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_set_source_rgb(cr, 0.75, 0, 0);
|
2019-05-26 10:23:24 -05:00
|
|
|
cairo_move_to(cr, x, y);
|
|
|
|
cairo_line_to(cr, x + width, y);
|
|
|
|
cairo_line_to(cr, x + width, y + height);
|
|
|
|
cairo_line_to(cr, x, y + height);
|
|
|
|
cairo_line_to(cr, x, y);
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_fill(cr);
|
|
|
|
|
|
|
|
cairo_set_source_rgb(cr, 1, 1, 1);
|
2019-05-26 10:23:24 -05:00
|
|
|
cairo_move_to(cr, x, y);
|
|
|
|
cairo_line_to(cr, x + width, y);
|
|
|
|
cairo_line_to(cr, x + width, y + height);
|
|
|
|
cairo_line_to(cr, x, y + height);
|
|
|
|
cairo_line_to(cr, x, y);
|
2019-05-25 22:49:59 -05:00
|
|
|
cairo_stroke(cr);
|
2019-05-25 21:30:31 -05:00
|
|
|
}
|
|
|
|
|
2019-05-26 15:55:54 -05:00
|
|
|
static void draw_gauge_cluster(cairo_t *cr,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
double width,
|
|
|
|
double height) {
|
2019-05-26 10:13:42 -05:00
|
|
|
/*
|
|
|
|
* Paint canvas black
|
|
|
|
*/
|
|
|
|
cairo_set_source_rgb(cr, 0, 0, 0);
|
|
|
|
cairo_paint(cr);
|
|
|
|
|
2019-05-26 16:03:12 -05:00
|
|
|
draw_tachometer(cr,
|
|
|
|
x + width * 0.2,
|
|
|
|
y + height * 0.5,
|
|
|
|
height * 0.4);
|
|
|
|
|
2019-05-26 16:07:20 -05:00
|
|
|
draw_speedometer(cr,
|
|
|
|
x + width * 0.8,
|
|
|
|
y + height * 0.5,
|
|
|
|
height * 0.4);
|
|
|
|
|
2019-05-26 16:12:21 -05:00
|
|
|
draw_thermometer(cr,
|
|
|
|
x + width * 0.43,
|
|
|
|
y + height * 0.76,
|
|
|
|
height * 0.13);
|
|
|
|
|
2019-05-26 16:15:00 -05:00
|
|
|
draw_fuel_gauge(cr,
|
|
|
|
x + width * 0.57,
|
|
|
|
y + height * 0.76,
|
|
|
|
height * 0.13);
|
|
|
|
|
2019-05-26 16:21:03 -05:00
|
|
|
draw_mfd(cr,
|
|
|
|
x + width * 0.42,
|
|
|
|
y + height * 0.1,
|
|
|
|
width * 0.16,
|
|
|
|
height * 0.5);
|
2019-05-26 10:13:42 -05:00
|
|
|
}
|
|
|
|
|
2019-05-25 18:19:56 -05:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
Display *display;
|
|
|
|
Window win;
|
|
|
|
Pixmap buf;
|
|
|
|
GC gc;
|
|
|
|
|
2019-05-26 15:55:54 -05:00
|
|
|
int screen,
|
|
|
|
width = 1024,
|
2019-05-26 16:31:05 -05:00
|
|
|
height = 480;
|
2019-05-25 18:19:56 -05:00
|
|
|
|
|
|
|
XGCValues values = {
|
|
|
|
.foreground = 0x000000,
|
|
|
|
.background = 0xffffff,
|
|
|
|
.graphics_exposures = 0
|
|
|
|
};
|
|
|
|
|
|
|
|
cairo_surface_t *sfc;
|
2019-05-26 10:17:06 -05:00
|
|
|
cairo_t *cr;
|
2019-05-25 18:19:56 -05:00
|
|
|
|
|
|
|
XEvent e;
|
|
|
|
|
|
|
|
if ((display = XOpenDisplay(NULL)) == NULL)
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
screen = DefaultScreen(display);
|
2019-05-26 15:55:54 -05:00
|
|
|
win = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, width, height, 0, 0, 0);
|
2019-05-25 18:19:56 -05:00
|
|
|
gc = XCreateGC(display, win, GCForeground | GCBackground | GCGraphicsExposures, &values);
|
2019-05-26 15:55:54 -05:00
|
|
|
buf = XCreatePixmap(display, win, width, height, 24);
|
2019-05-25 18:19:56 -05:00
|
|
|
|
|
|
|
XSelectInput(display, win, ExposureMask | ButtonPressMask | KeyPressMask);
|
|
|
|
XMapWindow(display, win);
|
|
|
|
|
2019-05-26 15:55:54 -05:00
|
|
|
sfc = cairo_xlib_surface_create(display, buf, DefaultVisual(display, screen), width, height);
|
|
|
|
cairo_xlib_surface_set_size(sfc, width, height);
|
2019-05-25 18:19:56 -05:00
|
|
|
|
2019-05-26 10:17:06 -05:00
|
|
|
cr = cairo_create(sfc);
|
2019-05-25 18:19:56 -05:00
|
|
|
|
2019-05-26 15:55:54 -05:00
|
|
|
draw_gauge_cluster(cr, 0, 0, width, height);
|
2019-05-25 18:19:56 -05:00
|
|
|
|
|
|
|
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:
|
2019-05-26 10:17:06 -05:00
|
|
|
cairo_destroy(cr);
|
2019-05-25 18:19:56 -05:00
|
|
|
|
|
|
|
cairo_surface_destroy(sfc);
|
|
|
|
XCloseDisplay(display);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|