head 1.4; access; symbols; locks; strict; comment @ * @; 1.4 date 2003.08.18.18.11.37; author cworth; state dead; branches; next 1.3; 1.3 date 2003.07.18.18.35.23; author cworth; state Exp; branches; next 1.2; 1.2 date 2003.04.25.20.31.20; author cworth; state Exp; branches; next 1.1; 1.1 date 2003.01.08.18.49.46; author cworth; state Exp; branches; next ; desc @@ 1.4 log @Added demos from OLS paper. @ text @#include #include #include #include #include #define EPSILON (1.0 / (2<<16)) #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) typedef struct win { Display *dpy; int scr; Window win; GC gc; Pixmap pix; int width, height; long event_mask; int needs_refresh; double tolerance; double zoom; } win_t; typedef struct callback_doc { void *callback; char *doc; } callback_doc_t; typedef int (*key_callback_t)(win_t *win); typedef struct key_binding { char *key; int is_alias; KeyCode keycode; key_callback_t callback; } key_binding_t; static void win_init(win_t *win, Display *dpy); static void win_deinit(win_t *win); static void win_refresh(win_t *win); static void win_select_events(win_t *win); static void win_handle_events(win_t *win); static void win_print_help(win_t *win); static int quit_cb(win_t *win); static int flatten_cb(win_t *win); static int smooth_cb(win_t *win); static const double DEFAULT_TOLERANCE = .1; static const callback_doc_t callback_doc[] = { { quit_cb, "Exit the program" }, { flatten_cb, "Decrease rendering accuracy, (tolerance *= 10)" }, { smooth_cb, "Increase rendering accuracy, (tolerance /= 10)" }, }; static key_binding_t key_binding[] = { /* Keysym, Alias, Keycode, callback */ { "Q", 0, 0, quit_cb }, { "greater",0, 0, smooth_cb }, { "period", 1, 0, smooth_cb }, { "less", 0, 0, flatten_cb }, { "comma", 1, 0, flatten_cb }, }; int main(int argc, char *argv[]) { win_t win; Display *dpy = XOpenDisplay(0); if (dpy == NULL) { fprintf(stderr, "Failed to open display: %s\n", XDisplayName(0)); return 1; } win_init(&win, dpy); win_print_help(&win); win_handle_events(&win); win_deinit(&win); XCloseDisplay(dpy); return 0; } static void win_refresh(win_t *win) { Display *dpy = win->dpy; double cx, cy; double radius, theta, theta_inc; cairo_t *xrs; Drawable drawable = win->pix; XFillRectangle(dpy, win->pix, win->gc, 0, 0, win->width, win->height); xrs = cairo_create(); cairo_set_target_drawable(xrs, dpy, drawable); cairo_set_rgb_color(xrs, 1, 1, 1); cx = win->width / 2.0; cy = win->height / 2.0; radius = sqrt(cx*cx+cy*cy); #define FINS 128.0 #define FIN_WIDTH (.25 * (2 * M_PI / FINS)) theta_inc = 2 * M_PI / FINS; for (theta=0; theta < 2 * M_PI; theta += theta_inc) { cairo_move_to(xrs, cx, cy); cairo_line_to(xrs, cx + radius * cos(theta), cy + radius * sin(theta)); cairo_line_to(xrs, cx + radius * cos(theta + FIN_WIDTH), cy + radius * sin(theta + FIN_WIDTH)); cairo_close_path(xrs); cairo_fill(xrs); } cairo_destroy(xrs); XCopyArea(win->dpy, win->pix, win->win, win->gc, 0, 0, win->width, win->height, 0, 0); } static void win_init(win_t *win, Display *dpy) { int i; Window root; XGCValues gcv; win->dpy = dpy; win->width = 400; win->height = 400; root = DefaultRootWindow(dpy); win->scr = DefaultScreen(dpy); win->win = XCreateSimpleWindow(dpy, root, 0, 0, win->width, win->height, 0, BlackPixel(dpy, win->scr), BlackPixel(dpy, win->scr)); win->pix = XCreatePixmap(dpy, win->win, win->width, win->height, DefaultDepth(dpy, win->scr)); gcv.foreground = BlackPixel(dpy, win->scr); win->gc = XCreateGC(dpy, win->pix, GCForeground, &gcv); XFillRectangle(dpy, win->pix, win->gc, 0, 0, win->width, win->height); for (i=0; i < ARRAY_SIZE(key_binding); i++) { KeySym keysym; keysym = XStringToKeysym(key_binding[i].key); if (keysym == NoSymbol) fprintf(stderr, "ERROR: No keysym for \"%s\"\n", key_binding[i].key); else key_binding[i].keycode = XKeysymToKeycode(dpy, keysym); } win->tolerance = DEFAULT_TOLERANCE; win_refresh(win); win->needs_refresh = 0; win_select_events(win); XMapWindow(dpy, win->win); } static void win_deinit(win_t *win) { XFreeGC(win->dpy, win->gc); XFreePixmap(win->dpy, win->pix); XDestroyWindow(win->dpy, win->win); } static void win_select_events(win_t *win) { win->event_mask = KeyPressMask | StructureNotifyMask | ExposureMask; XSelectInput(win->dpy, win->win, win->event_mask); } static char * get_callback_doc(void *callback) { int i; for (i=0; i < ARRAY_SIZE(callback_doc); i++) if (callback_doc[i].callback == callback) return callback_doc[i].doc; return ""; } static void win_print_help(win_t *win) { int i; printf("Xr spline demonstration\n"); for (i=0; i < ARRAY_SIZE(key_binding); i++) if (! key_binding[i].is_alias) printf("%s:\t%s\n", key_binding[i].key, get_callback_doc(key_binding[i].callback)); } static int win_handle_key_press(win_t *win, XKeyEvent *kev) { int i; for (i=0; i < ARRAY_SIZE(key_binding); i++) if (key_binding[i].keycode == kev->keycode) return (key_binding[i].callback)(win); return 0; } static void win_grow_pixmap(win_t *win) { Pixmap new; new = XCreatePixmap(win->dpy, win->win, win->width, win->height, DefaultDepth(win->dpy, win->scr)); XFillRectangle(win->dpy, new, win->gc, 0, 0, win->width, win->height); XCopyArea(win->dpy, win->pix, new, win->gc, 0, 0, win->width, win->height, 0, 0); XFreePixmap(win->dpy, win->pix); win->pix = new; win_refresh(win); } static void win_handle_configure(win_t *win, XConfigureEvent *cev) { int has_grown = 0; if (cev->width > win->width || cev->height > win->height) { has_grown = 1; } win->width = cev->width; win->height = cev->height; if (has_grown) { win_grow_pixmap(win); } else { win_refresh(win); } } static void win_handle_expose(win_t *win, XExposeEvent *eev) { XCopyArea(win->dpy, win->pix, win->win, win->gc, eev->x, eev->y, eev->width, eev->height, eev->x, eev->y); } static void win_handle_events(win_t *win) { int done; XEvent xev; while (1) { if (!XPending(win->dpy) && win->needs_refresh) { win_refresh(win); win->needs_refresh = 0; } XNextEvent(win->dpy, &xev); switch(xev.type) { case KeyPress: done = win_handle_key_press(win, &xev.xkey); if (done) return; break; case ConfigureNotify: win_handle_configure(win, &xev.xconfigure); break; case Expose: win_handle_expose(win, &xev.xexpose); break; } } } /* Callbacks */ static int quit_cb(win_t *win) { return 1; } static int flatten_cb(win_t *win) { win->tolerance *= 10; win->needs_refresh = 1; return 0; } static int smooth_cb(win_t *win) { win->tolerance /= 10; win->needs_refresh = 1; return 0; } @ 1.3 log @Updated to work with Cairo rather than Xr @ text @@ 1.2 log @Fixed up Makefile @ text @d6 1 a6 1 #include d101 1 a101 1 XrState *xrs; d106 1 a106 1 xrs = XrCreate(); d108 2 a109 2 XrSetTargetDrawable(xrs, dpy, drawable); XrSetRGBColor(xrs, 1, 1, 1); d120 5 a124 5 XrMoveTo(xrs, cx, cy); XrLineTo(xrs, cx + radius * cos(theta), cy + radius * sin(theta)); XrLineTo(xrs, cx + radius * cos(theta + FIN_WIDTH), cy + radius * sin(theta + FIN_WIDTH)); XrClosePath(xrs); XrFill(xrs); d127 1 a127 1 XrDestroy(xrs); @ 1.1 log @Added xrfreq @ text @d6 1 a6 1 #include d106 1 a106 1 xrs = XrCreate(dpy); d108 2 a109 2 XrSetDrawable(xrs, drawable); XrSetVisual(xrs, DefaultVisual(win->dpy, win->scr)); @