+/* 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) {
+ 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);
+
+# ifdef HAVE_XSHM_EXTENSION
+ if (st->use_shm)
+ XShmPutImage(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, False);
+ else
+
+ if (!st->use_shm)
+# endif
+ 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);
+
+}
+
+
+/* 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 ));