From http://www.jwz.org/xscreensaver/xscreensaver-5.22.tar.gz
[xscreensaver] / hacks / ripples.c
index 1fd3831f927267c2ffc52dae54c3ef1ce0e109c8..bffd2c68014f79a0de17d903f40c9cc909388ff2 100644 (file)
@@ -62,6 +62,7 @@ struct state {
   XImage *orig_map, *buffer_map;
   int ctab[256];
   Colormap colormap;
+  Screen *screen;
   int ncolors;
   int light;
 
@@ -90,6 +91,8 @@ struct state {
   int draw_count;
 
   int iterations, delay, rate, box, oily, stir, fluidity;
+  int duration;
+  time_t start_time;
 
   void (*draw_transparent) (struct state *st, short *src);
 
@@ -493,6 +496,7 @@ setup_X(struct state *st)
   XGetWindowAttributes(st->dpy, st->window, &xgwa);
   depth = xgwa.depth;
   st->colormap = xgwa.colormap;
+  st->screen = xgwa.screen;
   st->bigwidth = xgwa.width;
   st->bigheight = xgwa.height;
   st->visual = xgwa.visual;
@@ -529,6 +533,7 @@ setup_X(struct state *st)
 
     st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
                                               st->window, 0, 0);
+    st->start_time = time ((time_t) 0);
   } else {
     XGCValues gcv;
 
@@ -653,7 +658,8 @@ init_oily_colors(struct state *st)
 
   if (!mono_p) {
     colors = (XColor *)malloc(sizeof(*colors) * (st->ncolors+1));
-    make_smooth_colormap(st->dpy, st->visual, st->colormap, colors, &st->ncolors,
+    make_smooth_colormap(st->screen, st->visual, st->colormap,
+                         colors, &st->ncolors,
                          True, /* allocate */
                          False, /* not writable */
                          True); /* verbose (complain about failure) */
@@ -700,6 +706,7 @@ sinc(struct state *st, double x)
   int i;
   i = (int)(x * TABLE + 0.5);
   if (i >= TABLE) i = (TABLE-1) - (i-(TABLE-1));
+  if (i < 0) return 0.;
   return st->cos_tab[i];
 #elif 0
   return cos(x * M_PI/2);
@@ -715,19 +722,21 @@ sinc(struct state *st, double x)
 static void
 add_circle_drop(struct state *st, int x, int y, int radius, int dheight)
 {
-  int i, r2, cx, cy;
+  int r, r2, cx, cy;
   short *buf = (random()&1) ? st->bufferA : st->bufferB;
 
-  i = y * st->width + x;
   r2 = radius * radius;
 
+
   for (cy = -radius; cy <= radius; cy++)
     for (cx = -radius; cx <= radius; cx++) {
-      int r = cx*cx + cy*cy;
-      if (r <= r2) {
-        buf[i + cx + cy*st->width] =
-          (short)(dheight * sinc(st, sqrt(r)/radius));
-      }
+      int xx = x+cx;
+      int yy = y+cy;
+      if (xx < 0 || yy < 0 || xx >= st->width || yy >= st->height) {break;}
+      r = cx*cx + cy*cy;
+      if (r > r2) break;
+      buf[xx + yy*st->width] =
+        (short)(dheight * sinc(st, (radius > 0) ? sqrt(r)/radius : 0));
     }
 }
 
@@ -757,10 +766,13 @@ add_drop(struct state *st, ripple_mode mode, int drop)
   case ripple_blob: {
     double power;
 
+    int tmp_i, tmp_j;
     power = drop_dist[random() % (sizeof(drop_dist)/sizeof(drop_dist[0]))]; /* clumsy */
     dheight = (int)(drop * (power + 0.01));
-    newx = radius + border + (random() % (int)(st->width - 2*border - 2*radius*power));
-    newy = radius + border + (random() % (int)(st->height - 2*border - 2*radius*power));
+    tmp_i = (int)(st->width - 2*border - 2*radius*power);
+    tmp_j = (int)(st->height - 2*border - 2*radius*power);
+    newx = radius + border + ((tmp_i > 0) ? random() % tmp_i : 0);
+    newy = radius + border + ((tmp_j > 0) ? random() % tmp_j : 0);
     add_circle_drop(st, newx, newy, radius, dheight);
   }
   break;
@@ -770,12 +782,15 @@ add_drop(struct state *st, ripple_mode mode, int drop)
     int x;
     int cx, cy;
     short *buf = (random()&1) ? st->bufferA : st->bufferB;
+    int tmp_i, tmp_j;
 
     radius = (1 + (random() % 5)) * (1 + (random() % 5));
     dheight = drop / 128;
     if (random() & 1) dheight = -dheight;
-    newx = radius + border + (random() % (st->width - 2*border - 2*radius));
-    newy = radius + border + (random() % (st->height - 2*border - 2*radius));
+    tmp_i = st->width - 2*border - 2*radius;
+    tmp_j = st->height - 2*border - 2*radius;
+    newx = radius + border + ((tmp_i > 0) ? random() % tmp_i : 0);
+    newy = radius + border + ((tmp_j > 0) ? random() % tmp_j : 0);
     x = newy * st->width + newx;
     for (cy = -radius; cy <= radius; cy++)
       for (cx = -radius; cx <= radius; cx++)
@@ -945,6 +960,7 @@ ripples_init (Display *disp, Window win)
   st->window = win;
   st->iterations = 0;
   st->delay = get_integer_resource(disp, "delay", "Integer");
+  st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
   st->rate = get_integer_resource(disp, "rate", "Integer");
   st->box = get_integer_resource(disp, "box", "Integer");
   st->oily = get_boolean_resource(disp, "oily", "Boolean");
@@ -957,6 +973,8 @@ ripples_init (Display *disp, Window win)
 #endif /* HAVE_XSHM_EXTENSION */
   st->light = get_integer_resource(disp, "light", "Integer");
 
+  if (st->delay < 0) st->delay = 0;
+  if (st->duration < 1) st->duration = 1;
   if (st->fluidity <= 1) st->fluidity = 1;
   if (st->fluidity > 16) st->fluidity = 16; /* 16 = sizeof(short) */
   if (st->light < 0) st->light = 0;
@@ -1015,6 +1033,7 @@ ripples_draw (Display *dpy, Window window, void *closure)
       if (! st->img_loader) {  /* just finished */
         XWindowAttributes xgwa;
         XGetWindowAttributes(st->dpy, st->window, &xgwa);
+        st->start_time = time ((time_t) 0);
         st->orig_map = XGetImage (st->dpy, st->window, 0, 0, 
                                   xgwa.width, xgwa.height,
                                   ~0L, ZPixmap);
@@ -1023,6 +1042,16 @@ ripples_draw (Display *dpy, Window window, void *closure)
       return st->delay;
     }
 
+    if (!st->img_loader &&
+        st->start_time + st->duration < time ((time_t) 0)) {
+      XWindowAttributes xgwa;
+      XGetWindowAttributes(st->dpy, st->window, &xgwa);
+      st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
+                                                st->window, 0, 0);
+      st->start_time = time ((time_t) 0);
+      return st->delay;
+    }
+
     if (st->rate > 0 && (st->iterations % st->rate) == 0)
       add_drop(st, ripple_blob, -SPLASH);
     if (st->stir)
@@ -1065,18 +1094,22 @@ static const char *ripples_defaults[] =
   "*colors:            200",
   "*dontClearRoot:     True",
   "*delay:             50000",
+  "*duration:          120",
   "*rate:              5",
   "*box:               0",
-  "*water:             False",
+  "*water:             True",
   "*oily:              False",
   "*stir:              False",
   "*fluidity:          6",
-  "*light:             0",
+  "*light:             4",
   "*grayscale:                 False",
 #ifdef HAVE_XSHM_EXTENSION
   "*useSHM: True",
 #else
   "*useSHM: False",
+#endif
+#ifdef USE_IPHONE
+  "*ignoreRotation: True",
 #endif
   0
 };
@@ -1086,6 +1119,7 @@ static XrmOptionDescRec ripples_options[] =
   { "-colors", ".colors",      XrmoptionSepArg, 0},
   { "-colours",        ".colors",      XrmoptionSepArg, 0},
   {"-delay",   ".delay",       XrmoptionSepArg, 0},
+  {"-duration",        ".duration",    XrmoptionSepArg, 0 },
   {"-rate",    ".rate",        XrmoptionSepArg, 0},
   {"-box",     ".box",         XrmoptionSepArg, 0},
   {"-water",   ".water",       XrmoptionNoArg, "True"},