From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / hacks / rotzoomer.c
index 52b382f629d7298d5f0f9e64d936660876150581..e4cd8536c85cf3b4c740c6992961917acb62303a 100644 (file)
@@ -10,6 +10,8 @@
  * implied warranty.
  */
 
+/* (circle-mode by jwz, 4-Jun-2014; not finished yet.) */
+
 /*
  * Options:
  *
@@ -18,6 +20,7 @@
  * -n <num>    number of zoomboxes
  * -move       enable mobile zoomboxes
  * -sweep      enable sweep mode
+ * -circle     enable circle mode
  * -anim       enable snapshot mode
  * -no-anim    enable snapshot mode
  * -delay      delay in milliseconds
@@ -57,8 +60,11 @@ struct state {
   int num_zoom;
   int move;
   int sweep;
+  int circle;
   int delay;
   int anim;
+  int duration;
+  time_t start_time;
 
   async_load_state *img_loader;
 
@@ -75,16 +81,36 @@ rotzoom (struct state *st, struct zoom_area *za)
   int x, y, c, s, zoom, z;
   int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
   int ox = 0, oy = 0;
+  int w2 = (za->w/2) * (za->w/2);
 
   z = 8100 * sin (M_PI * za->a2 / 8192);
   zoom = 8192 + z;
 
-  c = zoom * cos (M_PI * za->a1 / 8192);
-  s = zoom * sin (M_PI * za->a1 / 8192);
   for (y = za->y; y <= y2; y++) {
     for (x = za->x; x <= x2; x++) {
-      ox = (x * c + y * s) >> 13;
-      oy = (-x * s + y * c) >> 13;
+      c = zoom * cos (M_PI * za->a1 / 8192);
+      s = zoom * sin (M_PI * za->a1 / 8192);
+      if (st->circle) {
+        int cx = za->x + za->w / 2;
+        int cy = za->y + za->h / 2;
+        int dx = x - cx;
+        int dy = y - cy;
+        int d2 = (dx*dx) + (dy*dy);
+
+        if (d2 > w2) {
+          ox = x;
+          oy = y;
+        } else {
+          double r = sqrt ((double) d2);
+          double th = atan ((double)dy / (double) (dx == 0 ? 1 : dx));
+          th += M_PI * (za->a1 / 300.0);
+          ox = 10 + cx + (int) (r * cos(th));
+          oy = 10 + cy + (int) (r * sin(th));
+        }
+      } else {
+        ox = (x * c + y * s) >> 13;
+        oy = (-x * s + y * c) >> 13;
+      }
 
       while (ox < 0)
         ox += st->width;
@@ -100,7 +126,7 @@ rotzoom (struct state *st, struct zoom_area *za)
   }
 
   za->a1 += za->inc1;          /* Rotation angle */
-  za->a1 &= 0x3fff;;
+  za->a1 &= 0x3fff;
 
   za->a2 += za->inc2;          /* Zoom */
   za->a2 &= 0x3fff;
@@ -164,6 +190,38 @@ reset_zoom (struct state *st, struct zoom_area *za)
     za->a2 = 0;
     za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
     za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
+  } else if (st->circle) {
+
+    za->w = 50 + random() % 300;
+    if (za->w > st->width / 3)
+      za->w = st->width / 3;
+    if (za->w > st->height / 3)
+      za->w = st->height / 3;
+    za->h = za->w;
+
+    za->ww = st->width - za->w;
+    za->hh = st->height - za->h;
+
+    za->x = (za->ww ? random() % za->ww : 0);
+    za->y = (za->hh ? random() % za->hh : 0);
+
+    za->dx = 0;
+    za->dy = 0;
+    za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
+
+    if (st->anim) {
+      za->n = 50 + random() % 1000;
+      za->a1 = 0;
+      za->a2 = 0;
+    } else {
+      za->n = 5 + random() % 10;
+      za->a1 = random ();
+      za->a2 = random ();
+    }
+
+    za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
+    za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
+
   } else {
     za->w = 50 + random() % 300;
     za->h = 50 + random() % 300;
@@ -176,8 +234,8 @@ reset_zoom (struct state *st, struct zoom_area *za)
     za->ww = st->width - za->w;
     za->hh = st->height - za->h;
 
-    za->x = (random() % za->ww);
-    za->y = (random() % za->hh);
+    za->x = (za->ww ? random() % za->ww : 0);
+    za->y = (za->hh ? random() % za->hh : 0);
 
     za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
     za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
@@ -208,7 +266,7 @@ create_zoom (struct state *st)
 {
   struct zoom_area *za;
 
-  za = malloc (sizeof (struct zoom_area));
+  za = calloc (1, sizeof (struct zoom_area));
   reset_zoom (st, za);
 
   return za;
@@ -264,13 +322,15 @@ init_hack (struct state *st)
 {
   int i;
 
+  st->start_time = time ((time_t *) 0);
   st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *));
   for (i = 0; i < st->num_zoom; i++) {
     st->zoom_box[i] = create_zoom (st);
   }
 
-  memcpy (st->buffer_map->data, st->orig_map->data,
-          st->height * st->buffer_map->bytes_per_line);
+  if (st->height && st->orig_map->data)
+    memcpy (st->buffer_map->data, st->orig_map->data,
+           st->height * st->buffer_map->bytes_per_line);
 
   DisplayImage(st, 0, 0, st->width, st->height);
 }
@@ -280,7 +340,7 @@ static unsigned long
 rotzoomer_draw (Display *disp, Window win, void *closure)
 {
   struct state *st = (struct state *) closure;
-  int delay = (st->delay * 1000);
+  int delay = st->delay;
   int i;
 
   if (st->img_loader)   /* still loading */
@@ -294,6 +354,16 @@ rotzoomer_draw (Display *disp, Window win, 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;
+  }
+
   for (i = 0; i < st->num_zoom; i++) {
     if (st->move || st->sweep)
       update_position (st->zoom_box[i]);
@@ -389,11 +459,16 @@ rotzoomer_init (Display *dpy, Window window)
     st->move = True;
   else if (!strcasecmp (s, "sweep"))
     st->sweep = True;
+  else if (!strcasecmp (s, "circle"))
+    st->circle = True;
   else
     fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
 
   st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
   st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+  st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+  if (st->delay < 0) st->delay = 0;
+  if (st->duration < 1) st->duration = 1;
 
   /* In sweep or static mode, we want only one box */
   if (st->sweep || !st->anim)
@@ -403,6 +478,13 @@ rotzoomer_init (Display *dpy, Window window)
   if (!st->anim)
     st->sweep = 0;
 
+  if (st->circle) {
+    st->move = 0;
+    st->sweep = 0;
+  }
+
+  st->start_time = time ((time_t *) 0);
+
   setup_X (st);
 
   return st;
@@ -417,6 +499,12 @@ rotzoomer_reshape (Display *dpy, Window window, void *closure,
 static Bool
 rotzoomer_event (Display *dpy, Window window, void *closure, XEvent *event)
 {
+  struct state *st = (struct state *) closure;
+  if (screenhack_event_helper (dpy, window, event))
+    {
+      st->start_time = 0;
+      return True;
+    }
   return False;
 }
 
@@ -431,6 +519,7 @@ rotzoomer_free (Display *dpy, Window window, void *closure)
 static const char *rotzoomer_defaults[] = {
   ".background: black",
   ".foreground: white",
+  "*fpsSolid:  true",
 #ifdef HAVE_XSHM_EXTENSION
   "*useSHM: True",
 #else
@@ -439,7 +528,12 @@ static const char *rotzoomer_defaults[] = {
   "*anim: True",
   "*mode: stationary",
   "*numboxes: 2",
-  "*delay: 10",
+  "*delay: 10000",
+  "*duration: 120",
+#ifdef HAVE_MOBILE
+  "*ignoreRotation: True",
+  "*rotateImages:   True",
+#endif
   0
 };
 
@@ -450,12 +544,14 @@ static XrmOptionDescRec rotzoomer_options[] = {
   { "-mode",   ".mode",        XrmoptionSepArg, 0      },
   { "-move",   ".mode",        XrmoptionNoArg, "move"  },
   { "-sweep",  ".mode",        XrmoptionNoArg, "sweep" },
+  { "-circle", ".mode",        XrmoptionNoArg, "circle"},
   { "-anim",   ".anim",        XrmoptionNoArg, "True"  },
   { "-no-anim",        ".anim",        XrmoptionNoArg, "False" },
   { "-delay",  ".delay",       XrmoptionSepArg, 0      },
+  {"-duration",        ".duration",    XrmoptionSepArg, 0      },
   { "-n",      ".numboxes",    XrmoptionSepArg, 0      },
   { 0, 0, 0, 0 }
 };
 
 
-XSCREENSAVER_MODULE ("Rotzoomer", rotzoomer)
+XSCREENSAVER_MODULE ("RotZoomer", rotzoomer)