summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-03-05 05:53:50 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-03-05 07:43:06 +0000
commit377f0762f2be40fc159c44bb6a4fa15b57037f1f (patch)
treec46335fc0df53950a93b61ec0ece0c8a3f21f097
parentbb18bd326b835799d9e835fcc2674af63b1dc7c7 (diff)
Add dragon
A demonstration of aligned-path stroking.
-rw-r--r--.gitignore1
-rw-r--r--Makefile4
-rw-r--r--dragon-demo.c227
3 files changed, 231 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 116f3c0..c7d4f7e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
chart-demo
+dragon-demo
fish-demo
flowers-demo
gears-demo
diff --git a/Makefile b/Makefile
index b172918..2d80825 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,7 @@ else
DEFINES+=-DHAVE_COGL=0
endif
-all: spinner-demo spiral-demo slideshow-demo tiger-demo fish-demo flowers-demo gears-demo gradient-demo chart-demo waterfall-demo
+all: spinner-demo spiral-demo slideshow-demo tiger-demo fish-demo flowers-demo gears-demo gradient-demo chart-demo waterfall-demo dragon-demo
ifeq ($(shell pkg-config --exists poppler-glib && echo 1), 1)
all: poppler-demo
@@ -72,6 +72,8 @@ chart-demo: chart-demo.c $(SOURCES) demo.h Makefile
$(CC) $(DEFINES) $(CFLAGS) -o $@ chart-demo.c $(SOURCES) $(LIBS)
waterfall-demo: waterfall-demo.c $(SOURCES) demo.h list.h Makefile
$(CC) $(DEFINES) $(CFLAGS) -o $@ waterfall-demo.c $(SOURCES) $(LIBS)
+dragon-demo: dragon-demo.c $(SOURCES) demo.h list.h Makefile
+ $(CC) $(DEFINES) $(CFLAGS) -o $@ dragon-demo.c $(SOURCES) $(LIBS)
clean:
rm -f *-demo
diff --git a/dragon-demo.c b/dragon-demo.c
new file mode 100644
index 0000000..cb31575
--- /dev/null
+++ b/dragon-demo.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright © 2007 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ * Inspiration (and path!) taken from
+ * http://labs.trolltech.com/blogs/2007/08/31/rasterizing-dragons/
+ */
+
+#include "demo.h"
+#include <string.h>
+#include <sys/time.h>
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+static inline int
+next_pot (int v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return v;
+}
+
+static cairo_bool_t
+direction (int i)
+{
+ int pivot, np2;
+
+ if (i < 2)
+ return TRUE;
+
+ np2 = next_pot (i + 1);
+ if (np2 == i + 1)
+ return TRUE;
+
+ pivot = np2 / 2 - 1;
+ return ! direction (2 * pivot - i);
+}
+
+static void
+path (cairo_t *cr, int step, int dir, int iterations)
+{
+ double dx, dy;
+ int i;
+
+ switch (dir) {
+ default:
+ case 0: dx = step; dy = 0; break;
+ case 1: dx = -step; dy = 0; break;
+ case 2: dx = 0; dy = step; break;
+ case 3: dx = 0; dy = -step; break;
+ }
+
+ for (i = 0; i < iterations; i++) {
+ cairo_rel_line_to (cr, dx, dy);
+
+ if (direction (i)) {
+ double t = dx;
+ dx = dy;
+ dy = -t;
+ } else {
+ double t = dx;
+ dx = -dy;
+ dy = t;
+ }
+ }
+}
+
+static void
+dragon (cairo_t *cr, int width, int height, int iterations)
+{
+ double cx, cy;
+
+ cx = .5 * width;
+ cy = .5 * height;
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_set_line_width (cr, 4.);
+
+ cairo_move_to (cr, cx, cy);
+ path (cr, 12, 0, iterations);
+ cairo_set_source_rgb (cr, 1, 0, 0);
+ cairo_stroke(cr);
+
+ cairo_move_to (cr, cx, cy);
+ path (cr, 12, 1, iterations);
+ cairo_set_source_rgb (cr, 0, 1, 0);
+ cairo_stroke(cr);
+
+ cairo_move_to (cr, cx, cy);
+ path (cr, 12, 2, iterations);
+ cairo_set_source_rgb (cr, 0, 0, 1);
+ cairo_stroke(cr);
+
+ cairo_move_to (cr, cx, cy);
+ path (cr, 12, 3, iterations);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_stroke(cr);
+}
+
+static int done;
+static void signal_handler(int sig)
+{
+ done = sig;
+}
+
+int main (int argc, char **argv)
+{
+ struct device *device;
+ struct timeval start, last_tty, last_fps, now;
+ int iterations = 1;
+
+ double delta;
+ int frame = 0;
+ int frames = 0;
+ int show_fps = 1;
+ int benchmark;
+ const char *version;
+ enum clip clip;
+
+ int n;
+
+ device = device_open(argc, argv);
+ version = device_show_version(argc, argv);
+ clip = device_get_clip(argc, argv);
+ benchmark = device_get_benchmark(argc, argv);
+ if (benchmark == 0)
+ benchmark = 20;
+ if (benchmark > 0)
+ show_fps = 0;
+
+ signal(SIGHUP, signal_handler);
+
+ for (n = 1; n < argc; n++) {
+ if (strcmp (argv[n], "--hide-fps") == 0)
+ show_fps = 0;
+ }
+
+ gettimeofday(&start, 0); now = last_tty = last_fps = start;
+ do {
+ struct framebuffer *fb = device->get_framebuffer (device);
+ cairo_t *cr = cairo_create(fb->surface);
+
+ dragon(cr, device->width, device->height, iterations);
+ if (++iterations == 4096)
+ iterations = 1;
+
+ gettimeofday(&now, NULL);
+ if (show_fps && last_fps.tv_sec) {
+ fps_draw(cr, device->name, version, &last_fps, &now);
+ }
+ last_fps = now;
+
+ cairo_destroy(cr);
+
+ fb->show (fb);
+ fb->destroy (fb);
+
+ if (benchmark < 0 && 0) {
+ delta = now.tv_sec - last_tty.tv_sec;
+ delta += (now.tv_usec - last_tty.tv_usec)*1e-6;
+ frames++;
+ if (delta > 5) {
+ printf("%.2f fps\n", frames/delta);
+ last_tty = now;
+ frames = 0;
+ }
+ }
+
+ frame++;
+ if (benchmark > 0) {
+ delta = now.tv_sec - start.tv_sec;
+ delta += (now.tv_usec - start.tv_usec)*1e-6;
+ if (delta > benchmark) {
+ printf("dragon: %.2f fps\n", frame / delta);
+ break;
+ }
+ }
+ } while (!done);
+
+ if (benchmark < 0) {
+ struct framebuffer *fb = device->get_framebuffer (device);
+ cairo_t *cr = cairo_create(fb->surface);
+
+ dragon(cr, device->width, device->height, 2048);
+ cairo_destroy(cr);
+
+ fps_finish(fb, device->name, version);
+ fb->show (fb);
+ fb->destroy (fb);
+ pause();
+ }
+
+ return 0;
+}