diff options
Diffstat (limited to 'hacks/distort.c')
| -rw-r--r-- | hacks/distort.c | 897 |
1 files changed, 0 insertions, 897 deletions
diff --git a/hacks/distort.c b/hacks/distort.c deleted file mode 100644 index a3586cf..0000000 --- a/hacks/distort.c +++ /dev/null @@ -1,897 +0,0 @@ -/* -*- mode: C; tab-width: 4 -*- - * xscreensaver, Copyright (c) 1992-2018 Jamie Zawinski <jwz@jwz.org> - * - * 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. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -/* distort - * by Jonas Munsin (jmunsin@iki.fi) and Jamie Zawinski <jwz@jwz.org> - * TODO: - * -check the allocations in init_round_lense again, maybe make it possible again - * to use swamp without pre-allocating/calculating (although that - * makes it slower) - -swamp is memory hungry - * -more distortion matrices (fortunately, I'm out of ideas :) - * Stuff that would be cool but probably too much of a resource hog: - * -some kind of interpolation to avoid jaggies - * -large speed values leaves the image distorted - * program idea borrowed from a screensaver on a non-*NIX OS, - * - * 28 Sep 1999 Jonas Munsin (jmunsin@iki.fi) - * Added about 10x faster algortim for 8, 16 and 32 bpp (modifies pixels - * directly avoiding costly XPutPixle(XGetPixel()) calls, inspired by - * xwhirl made by horvai@clipper.ens.fr (Peter Horvai) and the XFree86 - * Xlib sources. - * This piece of code is really horrible, but it works, and at the moment - * I don't have time or inspiration to fix something that works (knock - * on wood). - * 08 Oct 1999 Jonas Munsin (jmunsin@iki.fi) - * Corrected several bugs causing references beyond allocated memory. - * 09 Oct 2016 Dave Odell (dmo2118@gmail.com) - * Updated for new xshm.c. - */ - -#include <math.h> -#include <time.h> -#include "screenhack.h" -/*#include <X11/Xmd.h>*/ -# include "xshm.h" - -#define CARD32 unsigned int -#define CARD16 unsigned short -#define CARD8 unsigned char - - -struct coo { - int x; - int y; - int r, r_change; - int xmove, ymove; -}; - -struct state { - Display *dpy; - Window window; - - struct coo xy_coo[10]; - - int delay, radius, speed, number, blackhole, vortex, magnify, reflect, slow; - int duration; - time_t start_time; - - XWindowAttributes xgwa; - GC gc; - unsigned long black_pixel; - - XImage *orig_map, *buffer_map; - unsigned long *buffer_map_cache; - - int ***from; - int ****from_array; - int *fast_from; - int from_size; - - int bpp_size; - - XShmSegmentInfo shm_info; - - void (*effect) (struct state *, int); - void (*draw) (struct state *, int); - void (*draw_routine) (struct state *st, XImage *, XImage *, int, int, int *); - - async_load_state *img_loader; - Pixmap pm; -}; - - -static void move_lense(struct state *, int); -static void swamp_thing(struct state *, int); -static void new_rnd_coo(struct state *, int); -static void init_round_lense(struct state *st); -static void reflect_draw(struct state *, int); -static void plain_draw(struct state *, int); - -static void fast_draw_8 (struct state *st, XImage *, XImage *, int, int, int *); -static void fast_draw_16(struct state *st, XImage *, XImage *, int, int, int *); -static void fast_draw_32(struct state *st, XImage *, XImage *, int, int, int *); -static void generic_draw(struct state *st, XImage *, XImage *, int, int, int *); - - -static void distort_finish_loading (struct state *); - -static void -distort_reset (struct state *st) -{ - char *s; - int i; - - st->start_time = 0; - - XGetWindowAttributes (st->dpy, st->window, &st->xgwa); - - st->delay = get_integer_resource(st->dpy, "delay", "Integer"); - st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); - st->radius = get_integer_resource(st->dpy, "radius", "Integer"); - st->speed = get_integer_resource(st->dpy, "speed", "Integer"); - st->number = get_integer_resource(st->dpy, "number", "Integer"); - - st->blackhole = get_boolean_resource(st->dpy, "blackhole", "Boolean"); - st->vortex = get_boolean_resource(st->dpy, "vortex", "Boolean"); - st->magnify = get_boolean_resource(st->dpy, "magnify", "Boolean"); - st->reflect = get_boolean_resource(st->dpy, "reflect", "Boolean"); - st->slow = get_boolean_resource(st->dpy, "slow", "Boolean"); - - if (st->xgwa.width > 2560) st->radius *= 3; /* Retina displays */ - - if (st->delay < 0) st->delay = 0; - if (st->duration < 1) st->duration = 1; - - st->effect = NULL; - s = get_string_resource(st->dpy, "effect", "String"); - if (s && !strcasecmp(s,"swamp")) - st->effect = &swamp_thing; - else if (s && !strcasecmp(s,"bounce")) - st->effect = &move_lense; - else if (s && !strcasecmp(s,"none")) - ; - else if (s && *s) - fprintf(stderr,"%s: bogus effect: %s\n", progname, s); - if (s) free (s); - - if (st->effect == NULL && st->radius == 0 && st->speed == 0 && st->number == 0 - && !st->blackhole && !st->vortex && !st->magnify && !st->reflect) { -/* if no cmdline options are given, randomly choose one of: - * -radius 125 -number 4 -speed 1 -bounce - * -radius 125 -number 4 -speed 1 -blackhole - * -radius 125 -number 4 -speed 1 -vortex - * -radius 125 -number 4 -speed 1 -vortex -magnify - * -radius 125 -number 4 -speed 1 -vortex -magnify -blackhole - * -radius 250 -number 1 -speed 2 -bounce - * -radius 250 -number 1 -speed 2 -blackhole - * -radius 250 -number 1 -speed 2 -vortex - * -radius 250 -number 1 -speed 2 -vortex -magnify - * -radius 250 -number 1 -speed 2 -vortex -magnify -blackhole - * -radius 80 -number 1 -speed 2 -reflect - * -radius 125 -number 3 -speed 2 -reflect - * jwz: not these - * -radius 125 -number 4 -speed 2 -swamp - * -radius 125 -number 4 -speed 2 -swamp -blackhole - * -radius 125 -number 4 -speed 2 -swamp -vortex - * -radius 125 -number 4 -speed 2 -swamp -vortex -magnify - * -radius 125 -number 4 -speed 2 -swamp -vortex -magnify -blackhole - */ - - i = (random() % 12 /* 17 */); - - st->draw = &plain_draw; - - switch (i) { - case 0: - st->radius=125;st->number=4;st->speed=1; - st->effect=&move_lense;break; - case 1: - st->radius=125;st->number=4;st->speed=1;st->blackhole=1; - st->effect=&move_lense;break; - case 2: - st->radius=125;st->number=4;st->speed=1;st->vortex=1; - st->effect=&move_lense;break; - case 3: - st->radius=125;st->number=4;st->speed=1;st->vortex=1;st->magnify=1; - st->effect=&move_lense;break; - case 4: - st->radius=125;st->number=4;st->speed=1;st->vortex=1;st->magnify=1;st->blackhole=1; - st->effect=&move_lense;break; - case 5: - st->radius=250;st->number=1;st->speed=2; - st->effect=&move_lense;break; - case 6: - st->radius=250;st->number=1;st->speed=2;st->blackhole=1; - st->effect=&move_lense;break; - case 7: - st->radius=250;st->number=1;st->speed=2;st->vortex=1; - st->effect=&move_lense;break; - case 8: - st->radius=250;st->number=1;st->speed=2;st->vortex=1;st->magnify=1; - st->effect=&move_lense;break; - case 9: - st->radius=250;st->number=1;st->speed=2;st->vortex=1;st->magnify=1;st->blackhole=1; - st->effect=&move_lense;break; - - case 10: - st->radius=80;st->number=1;st->speed=2;st->reflect=1; - st->draw = &reflect_draw;st->effect = &move_lense;break; - case 11: - st->radius=125;st->number=4;st->speed=2;st->reflect=1; - st->draw = &reflect_draw;st->effect = &move_lense;break; - -#if 0 /* jwz: not these */ - case 12: - st->radius=125;st->number=4;st->speed=2; - effect=&swamp_thing;break; - case 13: - st->radius=125;st->number=4;st->speed=2;st->blackhole=1; - effect=&swamp_thing;break; - case 14: - st->radius=125;st->number=4;st->speed=2;st->vortex=1; - effect=&swamp_thing;break; - case 15: - st->radius=125;st->number=4;st->speed=2;st->vortex=1;st->magnify=1; - effect=&swamp_thing;break; - case 16: - st->radius=125;st->number=4;st->speed=2;st->vortex=1;st->magnify=1;st->blackhole=1; - effect=&swamp_thing;break; -#endif - - default: - abort(); break; - } - } - - /* never allow the radius to be too close to the min window dimension - */ - if (st->radius > st->xgwa.width * 0.3) st->radius = st->xgwa.width * 0.3; - if (st->radius > st->xgwa.height * 0.3) st->radius = st->xgwa.height * 0.3; - - - /* -swamp mode consumes vast amounts of memory, proportional to radius -- - so throttle radius to a small-ish value (60 => ~30MB.) - */ - if (st->effect == &swamp_thing && st->radius > 60) - st->radius = 60; - - if (st->delay < 0) - st->delay = 0; - if (st->radius <= 0) - st->radius = 60; - if (st->speed <= 0) - st->speed = 2; - if (st->number <= 0) - st->number=1; - if (st->number >= 10) - st->number=1; - if (st->effect == NULL) - st->effect = &move_lense; - if (st->reflect) { - st->draw = &reflect_draw; - st->effect = &move_lense; - } - if (st->draw == NULL) - st->draw = &plain_draw; -} - -static void * -distort_init (Display *dpy, Window window) -{ - struct state *st = (struct state *) calloc (1, sizeof(*st)); - XGCValues gcv; - long gcflags; - - st->dpy = dpy; - st->window = window; - - distort_reset (st); - - st->black_pixel = BlackPixelOfScreen( st->xgwa.screen ); - - gcv.function = GXcopy; - gcv.subwindow_mode = IncludeInferiors; - gcflags = GCFunction; - if (use_subwindow_mode_p(st->xgwa.screen, st->window)) /* see grabscreen.c */ - gcflags |= GCSubwindowMode; - st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv); - - /* On MacOS X11, XGetImage on a Window often gets an inexplicable BadMatch, - possibly due to the window manager having occluded something? It seems - nondeterministic. Loading the image into a pixmap instead fixes it. */ - if (st->pm) XFreePixmap (st->dpy, st->pm); - st->pm = XCreatePixmap (st->dpy, st->window, - st->xgwa.width, st->xgwa.height, st->xgwa.depth); - - st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window, - st->pm, 0, 0); - st->start_time = time ((time_t *) 0); - return st; -} - -static void -distort_finish_loading (struct state *st) -{ - int i; - - st->start_time = time ((time_t *) 0); - - if (! st->pm) abort(); - XClearWindow (st->dpy, st->window); - XCopyArea (st->dpy, st->pm, st->window, st->gc, - 0, 0, st->xgwa.width, st->xgwa.height, 0, 0); - if (st->orig_map) XDestroyImage (st->orig_map); - st->orig_map = XGetImage(st->dpy, st->pm, 0, 0, - st->xgwa.width, st->xgwa.height, - ~0L, ZPixmap); - if (st->buffer_map_cache) free (st->buffer_map_cache); - st->buffer_map_cache = malloc(sizeof(unsigned long)*(2*st->radius+st->speed+2)*(2*st->radius+st->speed+2)); - - if (st->buffer_map_cache == NULL) { - perror("distort"); - exit(EXIT_FAILURE); - } - - if (st->buffer_map) - destroy_xshm_image (st->dpy, st->buffer_map, &st->shm_info); - st->buffer_map = create_xshm_image(st->dpy, st->xgwa.visual, st->orig_map->depth, - ZPixmap, &st->shm_info, - 2*st->radius + st->speed + 2, - 2*st->radius + st->speed + 2); - - if ((st->buffer_map->byte_order == st->orig_map->byte_order) - && (st->buffer_map->depth == st->orig_map->depth) - && (st->buffer_map->format == ZPixmap) - && (st->orig_map->format == ZPixmap) - && !st->slow) { - switch (st->orig_map->bits_per_pixel) { - case 32: - st->draw_routine = &fast_draw_32; - st->bpp_size = sizeof(CARD32); - break; - case 16: - st->draw_routine = &fast_draw_16; - st->bpp_size = sizeof(CARD16); - break; - case 8: - st->draw_routine = &fast_draw_8; - st->bpp_size = sizeof(CARD8); - break; - default: - st->draw_routine = &generic_draw; - break; - } - } else { - st->draw_routine = &generic_draw; - } - init_round_lense(st); - - for (i = 0; i < st->number; i++) { - new_rnd_coo(st,i); - if (st->number != 1) - st->xy_coo[i].r = (i*st->radius)/(st->number-1); /* "randomize" initial */ - else - st->xy_coo[i].r = 0; - st->xy_coo[i].r_change = st->speed + (i%2)*2*(-st->speed); /* values a bit */ - st->xy_coo[i].xmove = st->speed + (i%2)*2*(-st->speed); - st->xy_coo[i].ymove = st->speed + (i%2)*2*(-st->speed); - } -} - -/* example: initializes a "see-trough" matrix */ -/* static void make_null_lense(struct state *st) -{ - int i, j; - for (i = 0; i < 2*radius+speed+2; i++) { - for (j = 0 ; j < 2*radius+speed+2 ; j++) { - from[i][j][0]=i; - from[i][j][1]=j; - } - } -} -*/ -static void convert(struct state *st) -{ - int *p; - int i, j; - if (st->fast_from) free (st->fast_from); - st->fast_from = calloc(1, sizeof(int)*((st->buffer_map->bytes_per_line/st->bpp_size)*(2*st->radius+st->speed+2) + 2*st->radius+st->speed+2)); - if (st->fast_from == NULL) { - perror("distort"); - exit(EXIT_FAILURE); - } - p = st->fast_from; - for (i = 0; i < 2*st->radius+st->speed+2; i++) { - for (j = 0; j < 2*st->radius+st->speed+2; j++) { - *(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) - = st->from[i][j][0] + st->xgwa.width*st->from[i][j][1]; - if (*(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) < 0 - || *(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) >= st->orig_map->height*st->orig_map->width) { - *(p + i + j*st->buffer_map->bytes_per_line/st->bpp_size) = 0; - } - } - } -} - -/* makes a lense with the Radius=loop and centred in - * the point (radius, radius) - */ -static void make_round_lense(struct state *st, int radius, int loop) -{ - int i, j; - - for (i = 0; i < 2*radius+st->speed+2; i++) { - for(j = 0; j < ((0 == st->bpp_size) ? (2*radius+st->speed+2) : (st->buffer_map->bytes_per_line/st->bpp_size)); j++) { - double r, d; - r = sqrt ((i-radius)*(i-radius)+(j-radius)*(j-radius)); - if (loop == 0) - d=0.0; - else - d=r/loop; - - if (r < loop-1) { - - if (st->vortex) { /* vortex-twist effect */ - double angle; - /* this one-line formula for getting a nice rotation angle is borrowed - * (with permission) from the whirl plugin for gimp, - * Copyright (C) 1996 Federico Mena Quintero - */ - /* 5 is just a constant used because it looks good :) */ - angle = 5*(1-d)*(1-d); - - /* Avoid atan2: DOMAIN error message */ - if ((radius-j) == 0.0 && (radius-i) == 0.0) { - st->from[i][j][0] = radius + cos(angle)*r; - st->from[i][j][1] = radius + sin(angle)*r; - } else { - st->from[i][j][0] = radius + - cos(angle - atan2(radius-j, -(radius-i)))*r; - st->from[i][j][1] = radius + - sin(angle - atan2(radius-j, -(radius-i)))*r; - } - if (st->magnify) { - r = sin(d*M_PI_2); - if (st->blackhole && r != 0) /* blackhole effect */ - r = 1/r; - st->from[i][j][0] = radius + (st->from[i][j][0]-radius)*r; - st->from[i][j][1] = radius + (st->from[i][j][1]-radius)*r; - } - } else { /* default is to magnify */ - r = sin(d*M_PI_2); - - /* raising r to different power here gives different amounts of - * distortion, a negative value sucks everything into a black hole - */ - /* r = r*r; */ - if (st->blackhole && r != 0) /* blackhole effect */ - r = 1/r; - /* bubble effect (and blackhole) */ - st->from[i][j][0] = radius + (i-radius)*r; - st->from[i][j][1] = radius + (j-radius)*r; - } - } else { /* not inside loop */ - st->from[i][j][0] = i; - st->from[i][j][1] = j; - } - } - } - - /* this is really just a quick hack to keep both the compability mode with all depths and still - * allow the custom optimized draw routines with the minimum amount of work */ - if (0 != st->bpp_size) { - convert(st); - } -} - -#ifndef EXIT_FAILURE -# define EXIT_FAILURE -1 -#endif - -static void allocate_lense(struct state *st) -{ - int i, j; - int s = ((0 != st->bpp_size) ? (st->buffer_map->bytes_per_line/st->bpp_size) : (2*st->radius+st->speed+2)); - /* maybe this should be redone so that from[][][] is in one block; - * then pointers could be used instead of arrays in some places (and - * maybe give a speedup - maybe also consume less memory) - */ - if (st->from) { - for (i = 0; i < st->from_size; i++) - if (st->from[i]) { - for (j = 0; j < st->from_size; j++) { - if (st->from[i][j]) free (st->from[i][j]); - } - free (st->from[i]); - } - free (st->from); - } - st->from_size = s; - st->from = (int ***)malloc(s*sizeof(int **)); - if (st->from == NULL) { - perror("distort"); - exit(EXIT_FAILURE); - } - for (i = 0; i < s; i++) { - st->from[i] = (int **)malloc((2*st->radius+st->speed+2) * sizeof(int *)); - if (st->from[i] == NULL) { - perror("distort"); - exit(EXIT_FAILURE); - } - for (j = 0; j < s; j++) { - st->from[i][j] = (int *)malloc(2 * sizeof(int)); - if (st->from[i][j] == NULL) { - perror("distort"); - exit(EXIT_FAILURE); - } - } - } -} - -/* from_array in an array containing precalculated from matrices, - * this is a double faced mem vs speed trade, it's faster, but eats - * _a lot_ of mem for large radius (is there a bug here? I can't see it) - */ -static void init_round_lense(struct state *st) -{ - int k; - - if (st->effect == &swamp_thing) { - if (st->from_array) free (st->from_array); - st->from_array = (int ****)malloc((st->radius+1)*sizeof(int ***)); - for (k=0; k <= st->radius; k++) { - allocate_lense(st); - make_round_lense(st, st->radius, k); - st->from_array[k] = st->from; - } - } else { /* just allocate one from[][][] */ - allocate_lense(st); - make_round_lense(st, st->radius,st->radius); - } -} - -/* If fast_draw_8, fast_draw_16 or fast_draw_32 are to be used, the following properties - * of the src and dest XImages must hold (otherwise the generic, slooow, method provided - * by X is to be used): - * src->byte_order == dest->byte_order - * src->format == ZPixmap && dest->format == ZPixmap - * src->depth == dest->depth == the depth the function in question asumes - * x and y is the coordinates in src from where to cut out the image from, - * distort_matrix is a precalculated array of how to distort the matrix - */ - -static void fast_draw_8(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) -{ - CARD8 *u = (CARD8 *)dest->data; - CARD8 *t = (CARD8 *)src->data + x + y*src->bytes_per_line/sizeof(CARD8); - - while (u < (CARD8 *)(dest->data + sizeof(CARD8)*dest->height - *dest->bytes_per_line/sizeof(CARD8))) { - *u++ = t[*distort_matrix++]; - } -} - -static void fast_draw_16(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) -{ - CARD16 *u = (CARD16 *)dest->data; - CARD16 *t = (CARD16 *)src->data + x + y*src->bytes_per_line/sizeof(CARD16); - - while (u < (CARD16 *)(dest->data + sizeof(CARD16)*dest->height - *dest->bytes_per_line/sizeof(CARD16))) { - *u++ = t[*distort_matrix++]; - } -} - -static void fast_draw_32(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) -{ - CARD32 *u = (CARD32 *)dest->data; - CARD32 *t = (CARD32 *)src->data + x + y*src->bytes_per_line/sizeof(CARD32); - - while (u < (CARD32 *)(dest->data + sizeof(CARD32)*dest->height - *dest->bytes_per_line/sizeof(CARD32))) { - *u++ = t[*distort_matrix++]; - } -} - -static void generic_draw(struct state *st, XImage *src, XImage *dest, int x, int y, int *distort_matrix) -{ - int i, j; - for (i = 0; i < dest->width; i++) - for (j = 0; j < dest->height; j++) - if (st->from[i][j][0] + x >= 0 && - st->from[i][j][0] + x < src->width && - st->from[i][j][1] + y >= 0 && - st->from[i][j][1] + y < src->height) - XPutPixel(dest, i, j, - XGetPixel(src, - st->from[i][j][0] + x, - st->from[i][j][1] + y)); -} - -/* generate an XImage of from[][][] and draw it on the screen */ -static void plain_draw(struct state *st, int k) -{ - if (st->xy_coo[k].x+2*st->radius+st->speed+2 > st->orig_map->width || - st->xy_coo[k].y+2*st->radius+st->speed+2 > st->orig_map->height) - return; - - st->draw_routine(st, st->orig_map, st->buffer_map, st->xy_coo[k].x, st->xy_coo[k].y, st->fast_from); - - put_xshm_image(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y, - 2*st->radius+st->speed+2, 2*st->radius+st->speed+2, &st->shm_info); -} - - -/* generate an XImage from the reflect algoritm submitted by - * Randy Zack <randy@acucorp.com> - * draw really got too big and ugly so I split it up - * it should be possible to use the from[][] to speed it up - * (once I figure out the algorithm used :) - */ -static void reflect_draw(struct state *st, int k) -{ - int i, j; - int cx, cy; - int ly, lysq, lx, ny, dist, rsq = st->radius * st->radius; - - cx = cy = st->radius; - if (st->xy_coo[k].ymove > 0) - cy += st->speed; - if (st->xy_coo[k].xmove > 0) - cx += st->speed; - - for(i = 0 ; i < 2*st->radius+st->speed+2; i++) { - ly = i - cy; - lysq = ly * ly; - ny = st->xy_coo[k].y + i; - if (ny >= st->orig_map->height) ny = st->orig_map->height-1; - for(j = 0 ; j < 2*st->radius+st->speed+2 ; j++) { - lx = j - cx; - dist = lx * lx + lysq; - if (dist > rsq || - ly < -st->radius || ly > st->radius || - lx < -st->radius || lx > st->radius) - XPutPixel( st->buffer_map, j, i, - XGetPixel( st->orig_map, st->xy_coo[k].x + j, ny )); - else if (dist == 0) - XPutPixel( st->buffer_map, j, i, st->black_pixel ); - else { - int x = st->xy_coo[k].x + cx + (lx * rsq / dist); - int y = st->xy_coo[k].y + cy + (ly * rsq / dist); - if (x < 0 || x >= st->xgwa.width || - y < 0 || y >= st->xgwa.height) - XPutPixel( st->buffer_map, j, i, st->black_pixel ); - else - XPutPixel( st->buffer_map, j, i, - XGetPixel( st->orig_map, x, y )); - } - } - } - - XPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y, - 2*st->radius+st->speed+2, 2*st->radius+st->speed+2); -} - -/* create a new, random coordinate, that won't interfer with any other - * coordinates, as the drawing routines would be significantly slowed - * down if they were to handle serveral layers of distortions - */ -static void new_rnd_coo(struct state *st, int k) -{ - int i; - int loop = 0; - - st->xy_coo[k].x = (random() % (st->xgwa.width-2*st->radius)); - st->xy_coo[k].y = (random() % (st->xgwa.height-2*st->radius)); - - for (i = 0; i < st->number; i++) { - if (i != k) { - if ((abs(st->xy_coo[k].x - st->xy_coo[i].x) <= 2*st->radius+st->speed+2) - && (abs(st->xy_coo[k].y - st->xy_coo[i].y) <= 2*st->radius+st->speed+2)) { - st->xy_coo[k].x = (random() % (st->xgwa.width-2*st->radius)); - st->xy_coo[k].y = (random() % (st->xgwa.height-2*st->radius)); - i=-1; /* ugly */ - } - } - if (loop++ > 1000) return; /* let's not get stuck */ - } -} - -/* move lens and handle bounces with walls and other lenses */ -static void move_lense(struct state *st, int k) -{ - int i; - - if (st->xy_coo[k].x + 2*st->radius + st->speed + 2 >= st->xgwa.width) - st->xy_coo[k].xmove = -abs(st->xy_coo[k].xmove); - if (st->xy_coo[k].x <= st->speed) - st->xy_coo[k].xmove = abs(st->xy_coo[k].xmove); - if (st->xy_coo[k].y + 2*st->radius + st->speed + 2 >= st->xgwa.height) - st->xy_coo[k].ymove = -abs(st->xy_coo[k].ymove); - if (st->xy_coo[k].y <= st->speed) - st->xy_coo[k].ymove = abs(st->xy_coo[k].ymove); - - st->xy_coo[k].x = st->xy_coo[k].x + st->xy_coo[k].xmove; - st->xy_coo[k].y = st->xy_coo[k].y + st->xy_coo[k].ymove; - - /* bounce against othe lenses */ - for (i = 0; i < st->number; i++) { - if ((i != k) - -/* This commented test is for rectangular lenses (not currently used) and - * the one used is for circular ones - && (abs(xy_coo[k].x - xy_coo[i].x) <= 2*radius) - && (abs(xy_coo[k].y - xy_coo[i].y) <= 2*radius)) { */ - - && ((st->xy_coo[k].x - st->xy_coo[i].x)*(st->xy_coo[k].x - st->xy_coo[i].x) - + (st->xy_coo[k].y - st->xy_coo[i].y)*(st->xy_coo[k].y - st->xy_coo[i].y) - <= 2*st->radius*2*st->radius)) { - - int x, y; - x = st->xy_coo[k].xmove; - y = st->xy_coo[k].ymove; - st->xy_coo[k].xmove = st->xy_coo[i].xmove; - st->xy_coo[k].ymove = st->xy_coo[i].ymove; - st->xy_coo[i].xmove = x; - st->xy_coo[i].ymove = y; - } - } - -} - -/* make xy_coo[k] grow/shrink */ -static void swamp_thing(struct state *st, int k) -{ - if (st->xy_coo[k].r >= st->radius) - st->xy_coo[k].r_change = -abs(st->xy_coo[k].r_change); - - if (st->xy_coo[k].r <= 0) { - st->from = st->from_array[0]; - st->draw(st,k); - st->xy_coo[k].r_change = abs(st->xy_coo[k].r_change); - new_rnd_coo(st,k); - st->xy_coo[k].r=st->xy_coo[k].r_change; - return; - } - - st->xy_coo[k].r = st->xy_coo[k].r + st->xy_coo[k].r_change; - - if (st->xy_coo[k].r >= st->radius) - st->xy_coo[k].r = st->radius; - if (st->xy_coo[k].r <= 0) - st->xy_coo[k].r=0; - - st->from = st->from_array[st->xy_coo[k].r]; -} - - -static unsigned long -distort_draw (Display *dpy, Window window, void *closure) -{ - struct state *st = (struct state *) closure; - int k; - - if (st->img_loader) /* still loading */ - { - st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); - if (! st->img_loader) { /* just finished */ - distort_finish_loading (st); - } - return st->delay; - } - - if (!st->img_loader && - st->start_time + st->duration < time ((time_t *) 0)) { - if (st->pm) XFreePixmap (st->dpy, st->pm); - st->pm = XCreatePixmap (st->dpy, st->window, - st->xgwa.width, st->xgwa.height, st->xgwa.depth); - st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window, - st->pm, 0, 0); - return st->delay; - } - - for (k = 0; k < st->number; k++) { - st->effect(st,k); - st->draw(st,k); - } - return st->delay; -} - -static void -distort_reshape (Display *dpy, Window window, void *closure, - unsigned int w, unsigned int h) -{ - struct state *st = (struct state *) closure; - XGetWindowAttributes (st->dpy, st->window, &st->xgwa); - /* XClearWindow (dpy, window); */ - /* Why doesn't this work? */ - if (st->orig_map) /* created in distort_finish_loading, might be early */ - XPutImage (st->dpy, st->window, st->gc, st->orig_map, - 0, 0, st->orig_map->width, st->orig_map->height, 0, 0); -} - -static Bool -distort_event (Display *dpy, Window window, void *closure, XEvent *event) -{ - struct state *st = (struct state *) closure; - if (screenhack_event_helper (dpy, window, event)) - { - distort_reset(st); - return True; - } - return False; -} - -static void -distort_free (Display *dpy, Window window, void *closure) -{ - struct state *st = (struct state *) closure; - int i, j; - XFreeGC (st->dpy, st->gc); - if (st->pm) XFreePixmap (dpy, st->pm); - if (st->orig_map) XDestroyImage (st->orig_map); - if (st->buffer_map) - destroy_xshm_image (st->dpy, st->buffer_map, &st->shm_info); - if (st->fast_from) free (st->fast_from); - if (st->from_array) free (st->from_array); - if (st->buffer_map_cache) free (st->buffer_map_cache); - - if (st->from) { - for (i = 0; i < st->from_size; i++) - if (st->from[i]) { - for (j = 0; j < st->from_size; j++) { - if (st->from[i][j]) free (st->from[i][j]); - } - free (st->from[i]); - } - free (st->from); - } - - free (st); -} - - - - -static const char *distort_defaults [] = { - "*dontClearRoot: True", - "*background: Black", - "*fpsSolid: true", -#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */ - "*visualID: Best", -#endif - - "*delay: 20000", - "*duration: 120", - "*radius: 0", - "*speed: 0", - "*number: 0", - "*slow: False", - "*vortex: False", - "*magnify: False", - "*reflect: False", - "*blackhole: False", - "*effect: none", -#ifdef HAVE_XSHM_EXTENSION - "*useSHM: False", /* xshm turns out not to help. */ -#endif /* HAVE_XSHM_EXTENSION */ -#ifdef HAVE_MOBILE - "*ignoreRotation: True", - "*rotateImages: True", -#endif - 0 -}; - -static XrmOptionDescRec distort_options [] = { - { "-delay", ".delay", XrmoptionSepArg, 0 }, - { "-duration", ".duration", XrmoptionSepArg, 0 }, - { "-radius", ".radius", XrmoptionSepArg, 0 }, - { "-speed", ".speed", XrmoptionSepArg, 0 }, - { "-number", ".number", XrmoptionSepArg, 0 }, - - { "-effect", ".effect", XrmoptionSepArg, 0 }, - { "-swamp", ".effect", XrmoptionNoArg, "swamp" }, - { "-bounce", ".effect", XrmoptionNoArg, "bounce" }, - - { "-reflect", ".reflect", XrmoptionNoArg, "True" }, - { "-vortex", ".vortex", XrmoptionNoArg, "True" }, - { "-magnify", ".magnify", XrmoptionNoArg, "True" }, - { "-blackhole", ".blackhole", XrmoptionNoArg, "True" }, - { "-slow", ".slow", XrmoptionNoArg, "True" }, -#ifdef HAVE_XSHM_EXTENSION - { "-shm", ".useSHM", XrmoptionNoArg, "True" }, - { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, -#endif /* HAVE_XSHM_EXTENSION */ - { 0, 0, 0, 0 } -}; - -XSCREENSAVER_MODULE ("Distort", distort) |
