http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.16.tar.gz
[xscreensaver] / hacks / fuzzyflakes.c
diff --git a/hacks/fuzzyflakes.c b/hacks/fuzzyflakes.c
new file mode 100644 (file)
index 0000000..9bb3c44
--- /dev/null
@@ -0,0 +1,262 @@
+/* fuzzyflakes, Copyright (c) 2004
+ *  Barry Dmytro <badcherry@mailc.net>
+ *
+ * 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.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+#define PI 3.14159265359
+
+typedef struct _flake_var
+{
+  double Ticks;
+  double XPos, YPos;
+  double TrueX;
+  double XOffset;
+  double Angle;
+} FlakeVariable;
+
+static struct _flake
+{ /* Struct containing the atrributes to our flakes */
+  int Arms;
+  int Thickness;
+  int BorderThickness;
+  int Radius;
+  unsigned long BordColor;
+  unsigned long ForeColor;
+  unsigned long BackColor;
+  int Layers;
+  int Density;
+  int Delay;
+  int FallingSpeed;
+  FlakeVariable *** Flakes; /* a dynamic array containing positions of all the flakes */
+  XGCValues GCValues;
+  unsigned long GCFlags;
+  GC GCVar;
+  Display * DisplayVar;
+  Window WindowVar;
+  XWindowAttributes XGWA;
+  struct _dbevar
+  {
+    Bool dbuf;
+    Pixmap b,ba,bb;
+  } DB;
+} Flake;
+
+static void
+InitFuzzyFlakes (Display *dpy, Window window)
+{
+  int i,j;
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  Flake.XGWA = xgwa;
+  Flake.DB.b = Flake.DB.ba = Flake.DB.bb = 0;
+  Flake.DB.dbuf                = get_boolean_resource ("doubleBuffer", "Boolean");
+  
+
+  if (Flake.DB.dbuf)
+    {
+      Flake.DB.ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
+      Flake.DB.bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
+      Flake.DB.b = Flake.DB.ba;
+    }
+  else
+    {
+      Flake.DB.b = window;
+    }
+
+
+  Flake.DisplayVar     = dpy;
+  Flake.WindowVar      = window;
+  Flake.Arms           = get_integer_resource ("arms", "Integer");
+  Flake.Thickness      = get_integer_resource ("thickness", "Integer");
+  Flake.BorderThickness        = get_integer_resource ("bthickness", "Integer");
+  Flake.Radius         = get_integer_resource ("radius", "Integer");
+  Flake.BordColor      = get_pixel_resource   ("border","Border",dpy,cmap);
+  Flake.ForeColor      = get_pixel_resource   ("foreground","Foreground",dpy,cmap);
+  Flake.BackColor      = get_pixel_resource   ("background","Background",dpy,cmap);
+  Flake.Density                = get_integer_resource ("density", "Integer");
+  Flake.Layers         = get_integer_resource ("layers", "Integer");
+  Flake.FallingSpeed   = get_integer_resource ("fallingspeed", "Integer");
+  Flake.Delay          = get_integer_resource ("delay", "Integer");
+  
+  if (Flake.Delay < 0) Flake.Delay = 0;
+
+  Flake.GCValues.foreground = get_pixel_resource("foreground","Foreground", dpy, cmap);
+  Flake.GCValues.background = get_pixel_resource("background","Background", dpy, cmap);
+  Flake.GCValues.line_width = Flake.Thickness;
+  Flake.GCValues.line_style = LineSolid;
+  Flake.GCValues.cap_style  = CapProjecting;
+  Flake.GCValues.join_style = JoinMiter;
+  Flake.GCFlags |= (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle);
+
+  Flake.GCVar = XCreateGC (Flake.DisplayVar, Flake.WindowVar, Flake.GCFlags, &Flake.GCValues);
+
+  Flake.Density = Flake.XGWA.width/200*Flake.Density;
+  Flake.Flakes = malloc(sizeof(FlakeVariable**)*Flake.Layers);
+  for(i=1;i<=Flake.Layers;i++)
+  {
+     Flake.Flakes[i-1] = malloc(sizeof(FlakeVariable*)*Flake.Density);
+     for(j=0;j<Flake.Density;j++)
+     {
+       Flake.Flakes[i-1][j] = malloc(sizeof(FlakeVariable));
+       Flake.Flakes[i-1][j]->XPos = random()%Flake.XGWA.width;
+       Flake.Flakes[i-1][j]->YPos = random()%Flake.XGWA.height;
+       Flake.Flakes[i-1][j]->Angle = random()%360*(PI/180);
+       Flake.Flakes[i-1][j]->Ticks = random()%360;
+       Flake.Flakes[i-1][j]->XOffset = random()%Flake.XGWA.height;
+     }
+  }
+}
+
+static void
+FuzzyFlakesMove(void)
+{
+  int i,j;
+  for(i=1;i<=Flake.Layers;i++)
+  {
+     for(j=0;j<Flake.Density;j++)
+     {
+       FlakeVariable * FlakeVar;
+       FlakeVar = Flake.Flakes[i-1][j];
+       FlakeVar->Ticks++;
+       FlakeVar->YPos = FlakeVar->YPos + ((double)Flake.FallingSpeed)/10/i;
+       FlakeVar->TrueX = (sin(FlakeVar->XOffset + FlakeVar->Ticks*(PI/180)*((double)Flake.FallingSpeed/10)))*10 + FlakeVar->XPos;
+       FlakeVar->Angle = FlakeVar->Angle + 0.005*((double)Flake.FallingSpeed/10);
+       if(FlakeVar->YPos - Flake.Radius > Flake.XGWA.height)
+       {
+         FlakeVar->Ticks = 0;
+        FlakeVar->YPos = 0 - Flake.Radius;
+       }
+     }
+  }
+}
+
+static void
+FuzzyFlakesDrawFlake(int XPos, int YPos, double AngleOffset, int Layer)
+{
+  int i;
+  double x,y,Angle,Radius;
+  
+  /* calculate the shrink factor debending on which layer we are drawing atm */
+  Radius = (double)(Flake.Radius - Layer * 5);
+  
+  /* draw the flake one arm at a time */
+  for(i=1;i<=Flake.Arms;i++)
+  {
+    int Diameter;
+    Diameter = (Flake.BorderThickness*2 + Flake.Thickness)/Layer;
+    /* compute the angle of this arm of the flake */
+    Angle = ((2*PI)/Flake.Arms)*i + AngleOffset;
+    /* calculate the x and y dispositions for this arm */
+    y=(int)(sin(Angle)*Radius);
+    x=(int)(cos(Angle)*Radius);
+    /* draw the base for the arm */
+    Flake.GCValues.line_width = Diameter;
+    XFreeGC(Flake.DisplayVar,Flake.GCVar);
+    Flake.GCVar = XCreateGC (Flake.DisplayVar, Flake.DB.b, Flake.GCFlags, &Flake.GCValues);
+    XSetForeground(Flake.DisplayVar,Flake.GCVar,Flake.BordColor);
+    XDrawLine(Flake.DisplayVar, Flake.DB.b, Flake.GCVar, XPos,YPos,XPos+x,YPos+y);
+    
+  }
+  /* draw the flake one arm at a time */
+  for(i=1;i<=Flake.Arms;i++)
+  {
+    /* compute the angle of this arm of the flake */
+    Angle = ((2*PI)/Flake.Arms)*i + AngleOffset;
+    /* calculate the x and y dispositions for this arm */
+    y=(int)(sin(Angle)*Radius);
+    x=(int)(cos(Angle)*Radius);
+    /* draw the inside of the arm */
+    Flake.GCValues.line_width = Flake.Thickness/Layer;
+    XFreeGC(Flake.DisplayVar,Flake.GCVar);
+    Flake.GCVar = XCreateGC (Flake.DisplayVar, Flake.DB.b, Flake.GCFlags, &Flake.GCValues);
+    XSetForeground(Flake.DisplayVar,Flake.GCVar,Flake.ForeColor);
+    XDrawLine(Flake.DisplayVar, Flake.DB.b, Flake.GCVar, XPos,YPos,XPos+x,YPos+y);
+  }
+}
+
+static void
+FuzzyFlakes (Display *dpy, Window window)
+{
+  int i,j;
+  
+  FuzzyFlakesMove();
+
+  XSetForeground(Flake.DisplayVar,Flake.GCVar,Flake.BackColor);
+  XFillRectangle(Flake.DisplayVar,Flake.DB.b,Flake.GCVar,0,0,Flake.XGWA.width,Flake.XGWA.height);
+
+  for(i=Flake.Layers;i>=1;i--)
+  {
+     for(j=0;j<Flake.Density;j++)
+     {
+       FuzzyFlakesDrawFlake(
+                       Flake.Flakes[i-1][j]->TrueX,
+                       Flake.Flakes[i-1][j]->YPos,
+               Flake.Flakes[i-1][j]->Angle,i);
+     }
+  }
+
+}
+
+\f
+char *progclass = "FuzzyFlakes";
+
+char *defaults [] = {
+  ".background:        pale green",
+  ".foreground:        pink",
+  ".border:    snow4",
+  "*arms:      5",
+  "*thickness: 10",
+  "*bthickness:        3",
+  "*radius:    20",
+  "*layers:    3",
+  "*density:   5",
+  "*fallingspeed:      10",
+  "*delay:     10000",
+  "*doubleBuffer:      True",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-arms",           ".arms",        XrmoptionSepArg, 0 },
+  { "-thickness",      ".thickness",   XrmoptionSepArg, 0 },
+  { "-bthickness",     ".bthickness",  XrmoptionSepArg, 0 },
+  { "-radius",         ".radius",      XrmoptionSepArg, 0 },
+  { "-layers",         ".layers",      XrmoptionSepArg, 0 },
+  { "-density",                ".density",     XrmoptionSepArg, 0 },
+  { "-speed",          ".fallingspeed",XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-db",             ".doubleBuffer", XrmoptionNoArg,  "True" },
+  { "-no-db",          ".doubleBuffer", XrmoptionNoArg,  "False" },
+  { 0, 0, 0, 0 }
+};
+
+void
+screenhack (Display *dpy, Window window)
+{
+  InitFuzzyFlakes (dpy, window);
+  while (1)
+    {
+      FuzzyFlakes (dpy, Flake.DB.b);
+      if (Flake.DB.dbuf)
+        {
+          XCopyArea (Flake.DisplayVar, Flake.DB.b, Flake.WindowVar, Flake.GCVar, 0, 0,
+                     Flake.XGWA.width, Flake.XGWA.height, 0, 0);
+          Flake.DB.b = (Flake.DB.b == Flake.DB.ba ? Flake.DB.bb : Flake.DB.ba);
+        }
+      screenhack_handle_events (dpy);
+      XSync (dpy, False);
+      if (Flake.Delay) usleep (Flake.Delay);
+    }
+}