X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Ffuzzyflakes.c;h=91762eac7ff55682a79c6d289251d7d77a600a88;hb=50be9bb40dc60130c99ffa568e6677779904ff70;hp=9bb3c44de356b7780f5c49c62445ded7e8302a93;hpb=9c9d475ff889ed8be02e8ce8c17da28b93278fca;p=xscreensaver diff --git a/hacks/fuzzyflakes.c b/hacks/fuzzyflakes.c index 9bb3c44d..91762eac 100644 --- a/hacks/fuzzyflakes.c +++ b/hacks/fuzzyflakes.c @@ -1,6 +1,18 @@ /* fuzzyflakes, Copyright (c) 2004 * Barry Dmytro * + * ! 2004.06.10 21:05 + * ! - Added support for resizing + * ! - Added a color scheme generation algorithm + * ! Thanks to from #vegans@irc.blitzed.org + * ! - Added random color generation + * ! - Fixed errors in the xml config file + * ! - Cleaned up a few inconsistencies in the code + * ! - Changed the default color to #EFBEA5 + * + * ! 2004.05.?? ??:?? + * ! -original creation + * * 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 @@ -12,251 +24,616 @@ #include #include "screenhack.h" -#define PI 3.14159265359 + +/* I have need of 1/3 and 2/3 constants later on */ +#define N1_3 0.3333333333 +#define N2_3 0.6666666666 typedef struct _flake_var { - double Ticks; - double XPos, YPos; - double TrueX; - double XOffset; - double Angle; + 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; +/* Struct containing the atrributes to our flakes */ +typedef struct _flake +{ + Display *dpy; + Window window; + + int Arms; + int Thickness; + int BorderThickness; + int Radius; + unsigned long BordColor; + unsigned long ForeColor; + unsigned long BackColor; + Bool RandomColors; + int Layers; + int Density; + int Delay; + int FallingSpeed; + struct _colors + { + char *Fore; + char *Bord; + char *Back; + } Colors; +/* a dynamic array containing positions of all the flakes */ + FlakeVariable ***Flakes; + XGCValues GCValues; + unsigned long GCFlags; + GC GCVar; + XWindowAttributes XGWA; + struct _dbevar + { + Bool dbuf; + Pixmap b, ba, bb; + } DB; } Flake; +/* + *This gets the pixel resource for a color: #ffffff + */ +static unsigned int +FuzzyFlakesColorResource(Flake *flake, char *Color) +{ + XColor color; + + if (!XParseColor(flake->dpy, flake->XGWA.colormap, Color, &color)) + { + fprintf(stderr, "%s: can't parse color %s", progname, Color); + return 0; + } + if (!XAllocColor(flake->dpy, flake->XGWA.colormap, &color)) + { + fprintf(stderr, "%s: can't allocate color %s", progname, Color); + return 0; + } + return color.pixel; +} + +/* + * This is a great color matching algorithm that I got from + * a friend of mine on #vegans@irc.blitzed.org + * She wrote it in PHP and I ported it over to C + * her site is http://beautifulfreak.net/ + */ +static int +FuzzyFlakesColorHelper(Flake *flake) +{ + unsigned int iR, iG, iB; + unsigned int iR0, iG0, iB0; + unsigned int iR1, iG1, iB1; + float fR, fG, fB; + float Max = 0, Min = 0, Lig, Sat; + float Hue, Hue0, Hue1; + float f1, f2; + float fR0, fG0, fB0; + float fR1, fG1, fB1; + float nR0, nG0, nB0; + float nR1, nG1, nB1; + XColor color; + + /* First convert from hex to dec */ + /* while splitting up the RGB values */ + if (!XParseColor(flake->dpy, flake->XGWA.colormap, + flake->Colors.Back, &color)) + { + fprintf(stderr, "%s: can't parse color %s", progname, + flake->Colors.Back); + return 1; + } + iR = color.red >> 8; + iG = color.green >> 8; + iB = color.blue >> 8; + + /* Convert from int to float */ + fR = iR; + fG = iG; + fB = iB; + + /* convert from 0-255 to 0-1 */ + fR = fR / 255; + fG = fG / 255; + fB = fB / 255; + + /* work out the lightness */ + if (fR >= fG && fR >= fB) + Max = fR; + if (fG >= fR && fG >= fB) + Max = fG; + if (fB >= fR && fB >= fG) + Max = fB; + + if (fR <= fG && fR <= fB) + Min = fR; + if (fG <= fR && fG <= fB) + Min = fG; + if (fB <= fR && fB <= fG) + Min = fB; + + Lig = (Max + Min) / 2; + + /* work out the saturation */ + if (Max == Min) + Sat = 0; + else + { + if (Lig < 0.5) + Sat = (Max - Min) / (Max + Min); + else + Sat = (Max - Min) / (2 - Max - Min); + } + + /* + * if our satration is too low we won't be + * able to see any objects + */ + if (Sat < 0.03) + { + return 1; + } + + /* work out the hue */ + if (fR == Max) + Hue = (fG - fB) / (Max - Min); + else if (fG == Max) + Hue = 2 + (fB - fR) / (Max - Min); + else + Hue = 4 + (fR - fG) / (Max - Min); + + Hue = Hue / 6; + + /* fine two equidistant hues */ + Hue0 = Hue + N1_3; + if (Hue0 > 1) + Hue0 = Hue0 - 1; + Hue1 = Hue0 + N1_3; + if (Hue1 > 1) + Hue1 = Hue1 - 1; + + /* convert the colors into hex codes */ + if (Lig < 0.5) + f2 = Lig * (1 + Sat); + else + f2 = (Lig + Sat) - (Lig * Sat); + + f1 = (2 * Lig) - f2; + + fR0 = (Hue0 + 1) / 3; + fR1 = (Hue1 + 1) / 3; + fG0 = Hue0; + fG1 = Hue1; + fB0 = (Hue0 - 1) / 3; + fB1 = (Hue1 - 1) / 3; + + if (fR0 < 0) + fR0 = fR0 + 1; + if (fR0 > 1) + fR0 = fR0 - 1; + if (fG0 < 0) + fG0 = fG0 + 1; + if (fG0 > 1) + fG0 = fG0 - 1; + if (fB0 < 0) + fB0 = fB0 + 1; + if (fB0 > 1) + fB0 = fB0 - 1; + + if (fR1 < 0) + fR1 = fR1 + 1; + if (fR1 > 1) + fR1 = fR1 - 1; + if (fG1 < 0) + fG1 = fG1 + 1; + if (fG1 > 1) + fG1 = fG1 - 1; + if (fB1 < 0) + fB1 = fB1 + 1; + if (fB1 > 1) + fB1 = fB1 - 1; + + if (6 * fR0 < 1) + nR0 = f1 + (f2 - f1) * 6 * fR0; + else if (2 * fR0 < 1) + nR0 = f2; + else if (3 * fR0 < 2) + nR0 = f1 + (f2 - f1) * (N2_3 - fR0) * 6; + else + nR0 = f1; + + if (6 * fG0 < 1) + nG0 = f1 + (f2 - f1) * 6 * fG0; + else if (2 * fG0 < 1) + nG0 = f2; + else if (3 * fG0 < 2) + nG0 = f1 + (f2 - f1) * (N2_3 - fG0) * 6; + else + nG0 = f1; + + if (6 * fB0 < 1) + nB0 = f1 + (f2 - f1) * 6 * fB0; + else if (2 * fB0 < 1) + nB0 = f2; + else if (3 * fB0 < 2) + nB0 = f1 + (f2 - f1) * (N2_3 - fB0) * 6; + else + nB0 = f1; + + if (6 * fR1 < 1) + nR1 = f1 + (f2 - f1) * 6 * fR1; + else if (2 * fR1 < 1) + nR1 = f2; + else if (3 * fR1 < 2) + nR1 = f1 + (f2 - f1) * (N2_3 - fR1) * 6; + else + nR1 = f1; + + if (6 * fG1 < 1) + nG1 = f1 + (f2 - f1) * 6 * fG1; + else if (2 * fG1 < 1) + nG1 = f2; + else if (3 * fG1 < 2) + nG1 = f1 + (f2 - f1) * (N2_3 - fG1) * 6; + else + nG1 = f1; + + if (6 * fB1 < 1) + nB1 = f1 + (f2 - f1) * 6 * fB1; + else if (2 * fB1 < 1) + nB1 = f2; + else if (3 * fB1 < 2) + nB1 = f1 + (f2 - f1) * (N2_3 - fB1) * 6; + else + nB1 = f1; + + /* at last convert them to a hex string */ + iR0 = nR0 * 255; + iG0 = nG0 * 255; + iB0 = nB0 * 255; + + iR1 = nR1 * 255; + iG1 = nG1 * 255; + iB1 = nB1 * 255; + + flake->Colors.Fore = malloc(sizeof(unsigned char) * 8); + flake->Colors.Bord = malloc(sizeof(unsigned char) * 8); + + sprintf(flake->Colors.Fore, "#%02X%02X%02X", iR0, iG0, iB0); + sprintf(flake->Colors.Bord, "#%02X%02X%02X", iR1, iG1, iB1); + + return 0; +} + static void -InitFuzzyFlakes (Display *dpy, Window window) +FuzzyFlakesInit(Flake *flake) { - 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; - } + int i, j; + XWindowAttributes xgwa; + + XGetWindowAttributes(flake->dpy, flake->window, &xgwa); + flake->XGWA = xgwa; + flake->DB.b = flake->DB.ba = flake->DB.bb = 0; + flake->DB.dbuf = get_boolean_resource(flake->dpy, "doubleBuffer", "Boolean"); +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + flake->DB.dbuf = False; +# endif - 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;jDB.dbuf) { - 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; + flake->DB.ba = + XCreatePixmap(flake->dpy, flake->window, xgwa.width, xgwa.height, xgwa.depth); + flake->DB.bb = + XCreatePixmap(flake->dpy, flake->window, xgwa.width, xgwa.height, xgwa.depth); + flake->DB.b = flake->DB.ba; + } + else + { + flake->DB.b = flake->window; + } + + flake->Arms = get_integer_resource(flake->dpy, "arms", "Integer"); + flake->Thickness = get_integer_resource(flake->dpy, "thickness", "Integer"); + flake->BorderThickness = get_integer_resource(flake->dpy, "bthickness", "Integer"); + flake->Radius = get_integer_resource(flake->dpy, "radius", "Integer"); + + flake->Density = get_integer_resource(flake->dpy, "density", "Integer"); + flake->Layers = get_integer_resource(flake->dpy, "layers", "Integer"); + flake->FallingSpeed = get_integer_resource(flake->dpy, "fallingspeed", "Integer"); + flake->Delay = get_integer_resource(flake->dpy, "delay", "Integer"); + if (flake->RandomColors == True) + flake->RandomColors = get_boolean_resource(flake->dpy, "randomColors", "Boolean"); + + if (flake->Delay < 0) + flake->Delay = 0; + + if (!flake->Colors.Back) + { + flake->Colors.Back = get_string_resource(flake->dpy, "color", "Color"); + if (!FuzzyFlakesColorResource(flake, flake->Colors.Back)) + { + fprintf(stderr, " reverting to random\n"); + flake->RandomColors = True; + } + + if (flake->RandomColors) + { + if (flake->Colors.Back) + free(flake->Colors.Back); + flake->Colors.Back = malloc(sizeof(unsigned char) * 8); + sprintf(flake->Colors.Back, "#%X%X%X%X%X%X", random() % 16, + random() % 16, random() % 16, random() % 16, random() % 16, + random() % 16); + } + + /* + * Here we establish our colormap based on what is in + * flake->Colors.Back + */ + if (FuzzyFlakesColorHelper(flake)) + { + fprintf(stderr, " reverting to random\n"); + if (flake->Colors.Back) + free(flake->Colors.Back); + flake->Colors.Back = malloc(sizeof(unsigned char) * 8); + sprintf(flake->Colors.Back, "#%X%X%X%X%X%X", random() % 16, + random() % 16, random() % 16, random() % 16, random() % 16, + random() % 16); + FuzzyFlakesColorHelper(flake); + } + + flake->ForeColor = FuzzyFlakesColorResource(flake, flake->Colors.Fore); + flake->BackColor = FuzzyFlakesColorResource(flake, flake->Colors.Back); + flake->BordColor = FuzzyFlakesColorResource(flake, flake->Colors.Bord); + + flake->GCValues.foreground = flake->ForeColor; + flake->GCValues.background = flake->BackColor; + flake->RandomColors = False; + } + + flake->GCValues.line_width = flake->Thickness; + flake->GCValues.cap_style = CapProjecting; + flake->GCValues.join_style = JoinMiter; + flake->GCFlags |= (GCLineWidth | GCCapStyle | GCJoinStyle); + + flake->GCVar = + XCreateGC(flake->dpy, flake->window, 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 * (M_PI / 180); + flake->Flakes[i - 1][j]->Ticks = random() % 360; + flake->Flakes[i - 1][j]->XOffset = random() % flake->XGWA.height; + } } - } } static void -FuzzyFlakesMove(void) +FuzzyFlakesFreeFlake(Flake *flake) { - int i,j; - for(i=1;i<=Flake.Layers;i++) - { - for(j=0;jLayers; i++) { - 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; - } + for (j = 0; j < flake->Density; j++) + { + free(flake->Flakes[i - 1][j]); + } + free(flake->Flakes[i - 1]); } - } + + if (flake->DB.bb) XFreePixmap(flake->dpy, flake->DB.bb); + if (flake->DB.ba) XFreePixmap(flake->dpy, flake->DB.ba); } static void -FuzzyFlakesDrawFlake(int XPos, int YPos, double AngleOffset, int Layer) +FuzzyFlakesMove(Flake *flake) { - 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); - } + 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 * (M_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 -FuzzyFlakes (Display *dpy, Window window) +FuzzyFlakesDrawFlake(Flake *flake, int XPos, int YPos, double AngleOffset, int Layer) { - int i,j; - - FuzzyFlakesMove(); + 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; - XSetForeground(Flake.DisplayVar,Flake.GCVar,Flake.BackColor); - XFillRectangle(Flake.DisplayVar,Flake.DB.b,Flake.GCVar,0,0,Flake.XGWA.width,Flake.XGWA.height); + Diameter = (flake->BorderThickness * 2 + flake->Thickness) / Layer; + /* compute the angle of this arm of the flake */ + Angle = ((2 * M_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->dpy, flake->GCVar); + flake->GCVar = + XCreateGC(flake->dpy, flake->DB.b, flake->GCFlags, + &flake->GCValues); + XSetForeground(flake->dpy, flake->GCVar, flake->BordColor); + XDrawLine(flake->dpy, 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 * M_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->dpy, flake->GCVar); + flake->GCVar = + XCreateGC(flake->dpy, flake->DB.b, flake->GCFlags, + &flake->GCValues); + XSetForeground(flake->dpy, flake->GCVar, flake->ForeColor); + XDrawLine(flake->dpy, flake->DB.b, flake->GCVar, XPos, YPos, + XPos + x, YPos + y); + } +} + +static void +FuzzyFlakes(Flake *flake) +{ + int i, j; - for(i=Flake.Layers;i>=1;i--) - { - for(j=0;jdpy, flake->GCVar, flake->BackColor); + XFillRectangle(flake->dpy, flake->DB.b, flake->GCVar, 0, 0, + flake->XGWA.width, flake->XGWA.height); + for (i = flake->Layers; i >= 1; i--) { - FuzzyFlakesDrawFlake( - Flake.Flakes[i-1][j]->TrueX, - Flake.Flakes[i-1][j]->YPos, - Flake.Flakes[i-1][j]->Angle,i); + for (j = 0; j < flake->Density; j++) + { + FuzzyFlakesDrawFlake(flake, + flake->Flakes[i - 1][j]->TrueX, + flake->Flakes[i - 1][j]->YPos, + flake->Flakes[i - 1][j]->Angle, i); + } } - } } - -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 -}; +static void * +fuzzyflakes_init (Display *dpy, Window window) +{ + Flake *flake = (Flake *) calloc (1, sizeof(*flake)); + flake->dpy = dpy; + flake->window = window; -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 } -}; + /* This is needed even if it is going to be set to false */ + flake->RandomColors = True; + + /* set up our colors amoung many other things */ + FuzzyFlakesInit(flake); -void -screenhack (Display *dpy, Window window) + return flake; +} + +static unsigned long +fuzzyflakes_draw (Display *dpy, Window window, void *closure) { - InitFuzzyFlakes (dpy, window); - while (1) + Flake *flake = (Flake *) closure; + + FuzzyFlakes(flake); + if (flake->DB.dbuf) + { + XCopyArea(flake->dpy, flake->DB.b, flake->window, + 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); + } + + return flake->Delay; +} + +static void +fuzzyflakes_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + Flake *flake = (Flake *) closure; + + if (flake->XGWA.width != w || flake->XGWA.height != h) { - 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); + FuzzyFlakesFreeFlake(flake); + FuzzyFlakesInit(flake); } } + +static Bool +fuzzyflakes_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +fuzzyflakes_free (Display *dpy, Window window, void *closure) +{ + Flake *flake = (Flake *) closure; + FuzzyFlakesFreeFlake(flake); + free(flake); +} + + +static const char *fuzzyflakes_defaults[] = { + "*color: #efbea5", + "*arms: 5", + "*thickness: 10", + "*bthickness: 3", + "*radius: 20", + "*layers: 3", + "*density: 5", + "*fallingspeed: 10", + "*delay: 10000", + "*doubleBuffer: True", + "*randomColors: False", + 0 +}; + +static XrmOptionDescRec fuzzyflakes_options[] = { + { "-color", ".color", XrmoptionSepArg, 0}, + { "-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"}, + { "-random-colors", ".randomColors", XrmoptionNoArg, "True"}, + { 0, 0, 0, 0} +}; + + +XSCREENSAVER_MODULE ("FuzzyFlakes", fuzzyflakes)