From f9c8a5242190d3b96cb51a4e651caccfb451f122 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 6 Nov 2013 20:09:48 -0800 Subject: [PATCH] Add a simple X-based demo program This is the same chart as in acre-test, but in an interactive program using Xlib and cairo. So far, the only interactivity is that it redraws the chart to match any changes to window size. --- Makefile | 9 ++- acre-x.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 acre-x.c diff --git a/Makefile b/Makefile index a14d677..b1fcaeb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -bin_PROGRAMS = acre-test +bin_PROGRAMS = acre-test acre-x acre_test_SOURCES = \ acre-test.c \ @@ -14,11 +14,18 @@ acre_test_CFLAGS=$$(pkg-config --cflags pangocairo lcms) \ -Wmissing-prototypes -Wmissing-declarations \ -Wnested-externs -Wno-unused-parameter +acre_x_LDFLAGS=$(acre_test_LDFLAGS) -lX11 + +acre_x_CFLAGS=$(acre_test_CFLAGS) + all: $(bin_PROGRAMS) acre-test: acre-test.o acre.o xmalloc.o $(CC) $(LDFLAGS) $(acre_test_LDFLAGS) $(acre_test_CFLAGS) $(CFLAGS) -o $@ $^ +acre-x: acre-x.o acre.o xmalloc.o + $(CC) $(LDFLAGS) $(acre_x_LDFLAGS) $(acre_x_CFLAGS) $(CFLAGS) -o $@ $^ + %.o: %.c $(CC) $(LDFLAGS) $(acre_test_LDFLAGS) $(acre_test_CFLAGS) $(CFLAGS) -c -o $@ $< diff --git a/acre-x.c b/acre-x.c new file mode 100644 index 0000000..4e2cd0f --- /dev/null +++ b/acre-x.c @@ -0,0 +1,182 @@ +/* acre - A cairo-based library for creating plots and charts. + * + * Copyright © 2009 Carl Worth + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +#include +#include + +#include "acre.h" +#include "math.h" + +static acre_t * +load_chart (void) +{ + acre_t *acre; + acre_data_t *data0, *data1, *data2; + int i; + + acre = acre_create (); + acre_set_x_axis_label (acre, "X axis"); + acre_set_y_axis_label (acre, "Y axis"); + + data0 = acre_data_create (); + data1 = acre_data_create (); + data2 = acre_data_create (); + + acre_data_set_name (data0, "Data 0"); + acre_data_set_name (data1, "Data 1"); + acre_data_set_name (data2, "Data 2"); + + for (i = 0; i <= 100; i++) { + acre_data_add_point_2d (data0, i, 0 - (i/3.0)*(i/3.0)); + } + + for (i = 0; i < 100; i++) { + double t = 1.0 - (i / 100.0); + acre_data_add_point_2d (data1, i, -1000 * (1.0 - t*t*t)); + } + + for (i = 0; i <= 1000; i++) { + double t, x, y; + t = i/10.0 - 50; + x = t + 50; + if (t == 0.0) + y = -200; + else + y = -1200 + 1000 * sin(t) / t; + acre_data_add_point_2d (data2, x, y); + } + + acre_add_data (acre, data0); + acre_add_data (acre, data1); + acre_add_data (acre, data2); + + acre_set_title (acre, "All the data"); + + return acre; +} + +static void +draw (Display *dpy, Window window, Visual *visual, acre_t *acre, + int width, int height) +{ + cairo_t *cr; + cairo_surface_t *surface; + + surface = cairo_xlib_surface_create (dpy, window, visual, + width, height); + cr = cairo_create (surface); + + /* Erase to white */ + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + + acre_draw (acre, cr, width, height); + + cairo_destroy (cr); + + cairo_surface_destroy (surface); +} + + +static void +handle_events(Display *dpy, Window window, Visual *visual, + acre_t *acre, int width, int height) +{ + XEvent xev; + KeyCode quit_code = XKeysymToKeycode (dpy, XStringToKeysym("Q")); + bool need_redraw = false; + + while (1) { + if (! XPending (dpy) && need_redraw) + draw (dpy, window, visual, acre, width, height); + + XNextEvent (dpy, &xev); + switch (xev.type) { + case KeyPress: + if (xev.xkey.keycode == quit_code) { + return; + } + break; + case ConfigureNotify: + width = xev.xconfigure.width; + height = xev.xconfigure.height; + break; + case Expose: + if (xev.xexpose.count == 0) + need_redraw = 1; + break; + } + } +} + +int +main (void) +{ + Display *dpy; + Window window, root; + Visual *visual; + acre_t *acre; + XSetWindowAttributes window_attr; + Colormap colormap; + unsigned long window_mask, event_mask; + unsigned long white; + + int width = 800; + int height = 600; + + acre = load_chart (); + + dpy = XOpenDisplay (NULL); + + if (dpy == NULL) { + fprintf(stderr, "Failed to open display %s\n", + XDisplayName(NULL)); + return 1; + } + + root = DefaultRootWindow (dpy); + white = WhitePixel (dpy, DefaultScreen (dpy)); + visual = DefaultVisual (dpy, DefaultScreen (dpy)); + colormap = XCreateColormap (dpy, root, visual, AllocNone); + event_mask = KeyPressMask | StructureNotifyMask | ExposureMask; + + window_mask = 0; + window_mask |= CWBackPixel; window_attr.background_pixel = white; + window_mask |= CWBorderPixel; window_attr.border_pixel = white; + window_mask |= CWColormap; window_attr.colormap = colormap; + window_mask |= CWEventMask; window_attr.event_mask = event_mask; + + window = XCreateWindow(dpy, root, 0, 0, width, height, 0, + DefaultDepth (dpy, DefaultScreen (dpy)), + InputOutput, visual, + window_mask, &window_attr); + + XMapWindow (dpy, window); + + handle_events (dpy, window, visual, acre, width, height); + + acre_destroy (acre); + + XDestroyWindow (dpy, window); + XCloseDisplay (dpy); + + return 0; +} -- 2.43.0