X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fwhirlygig.c;h=d46fcb6f9505d27b4ae25e6d4fac178678127c10;hp=3757f961be79a3894a8599351955f474f618208c;hb=4cecfc89e5e889c7232693897c06168fb378bd5c;hpb=c28aecf9fc41e3a03494bacf7279745425e2fa18 diff --git a/hacks/whirlygig.c b/hacks/whirlygig.c index 3757f961..d46fcb6f 100644 --- a/hacks/whirlygig.c +++ b/hacks/whirlygig.c @@ -16,36 +16,40 @@ #include #include "screenhack.h" +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + #define NCOLORS 100 #define FULL_CYCLE 429496729 #define START_ARC 0 #define END_ARC 23040 struct info { - Bool writable; /* Is the screen writable */ - double xspeed; /* A factor to modify the horizontal movement */ - double yspeed; /* A factor to modify vertical movement */ - double xamplitude; - double yamplitude; - int whirlies; /* How many whirlies per line do you want? */ - int nlines; /* How many lines of whirlies do you want? */ - int half_width; /* 1/2 the width of the screen */ - int half_height; - int speed; - int trail; - int color_modifier; - double xoffset; - double yoffset; - double offset_period; - int wrap; + Bool writable; /* Is the screen writable */ + double xspeed; /* A factor to modify the horizontal movement */ + double yspeed; /* A factor to modify vertical movement */ + double xamplitude; + double yamplitude; + int whirlies; /* How many whirlies per line do you want? */ + int nlines; /* How many lines of whirlies do you want? */ + int half_width; /* 1/2 the width of the screen */ + int half_height; + int speed; + int trail; + int color_modifier; + double xoffset; + double yoffset; + double offset_period; + int wrap; }; enum object_mode { spin_mode, funky_mode, circle_mode, linear_mode, test_mode, fun_mode, innie_mode, lissajous_mode } mode; -static void explain(int, struct info *, Display *, Window, GC); - +static void explain(int, int, struct info *, Display *, Window, GC); +static void draw_explain_string(int, int, Display *, Window, GC); static void spin(unsigned long int, struct info *, int *, int); static void funky(unsigned long int, struct info *, int *, int); static void circle(unsigned long int, struct info *, int *, int); @@ -55,8 +59,6 @@ static void lissajous(unsigned long int, struct info *, int *, int); static void test(unsigned long int, struct info *, int *, int); static void innie(unsigned long int, struct info *, int *, int, double); - - XColor colors[NCOLORS]; int ncolors = NCOLORS; char *progclass = "Whirlygig"; @@ -76,11 +78,16 @@ char *defaults [] = { "*trail: 0", "*color_modifier: -1", "*start_time: -1", - "*explain: 0", + "*explain: False", "*xoffset: 1.0", "*yoffset: 1.0", "*offset_period: 1", "*wrap: 0", + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", + "*useDBEClear: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ 0 }; @@ -116,65 +123,89 @@ XrmOptionDescRec options [] = { /* Tell the whirlies to be offset by this factor of a cos */ { "-offset_period", ".offset_period", XrmoptionSepArg, 0 }, /* Change the period of an offset cycle */ - { "-explain", ".explain", XrmoptionSepArg, 0 }, + { "-explain", ".explain", XrmoptionNoArg, "True" }, /* Specify whether or not to print an explanation of the function used. */ { "-wrap", ".wrap", XrmoptionSepArg, 0 }, /* Specify if you want whirlies which are out of the boundary of the screen to be wrapped around to the other side */ + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, { 0, 0, 0, 0 } }; +static const char spin_explanation[] = +"Spin mode is a simple sin/cos with every argument modified"; static const char funky_explanation[] = "Funky mode is me goofing off."; -static const char test_explanation[] = -"Test mode is a mode that I play around with ideas in."; - -static const char spin_explanation[] = -"Spin mode is a simple sin/cos with every argument modified"; - static const char circle_explanation[] = "Circle mode graphs the x and y positions as you trace the edge of a circle over time."; +static const char linear_explanation[] = +"Linear mode draws a straight line"; + +static const char test_explanation[] = +"Test mode is a mode that I play around with ideas in."; + static const char fun_explanation[] = "Fun mode is the coolest."; -static const char linear_explanation[] = -"I draw a straight line -- woo hoo"; +static const char innie_explanation[] = +"Innie mode does something or other. Looks cool, though."; static const char lissajous_explanation[] = -"This draws a slightly modified lissajous curve"; +"Lissajous mode draws a slightly modified lissajous curve"; static void -explain(int mode, struct info *info, Display *display, Window window, GC fgc) +explain(int xmode, int ymode, struct info *info, Display *display, Window window, GC fgc) { XClearWindow(display, window); - switch(mode) { - case spin_mode: - XDrawString(display, window, fgc, 50, info->half_height-100, spin_explanation, strlen(spin_explanation)); - break; - case funky_mode: - XDrawString(display, window, fgc, 50, info->half_height-100, funky_explanation, strlen(funky_explanation)); - break; - case circle_mode: - XDrawString(display, window, fgc, 50, info->half_height-100, circle_explanation, strlen(circle_explanation)); - break; - case fun_mode: - XDrawString(display, window, fgc, 50, info->half_height-100, fun_explanation, strlen(fun_explanation)); - break; - case linear_mode: - XDrawString(display, window, fgc, 50, info->half_height-100, linear_explanation, strlen(linear_explanation)); - break; - case lissajous_mode: - XDrawString(display, window, fgc, 50, info->half_height-100, lissajous_explanation, strlen(linear_explanation)); - - } + draw_explain_string(xmode, info->half_height-100, display, window, fgc); +/* draw_explain_string(ymode, info->half_height-50, display, window, fgc);*/ XSync(display, False); sleep(3); XClearWindow(display, window); } +static void +draw_explain_string(int mode, int offset, Display *display, Window window, GC fgc) +{ + switch(mode) { + case spin_mode: + XDrawString(display, window, fgc, 50, offset, spin_explanation, + strlen(spin_explanation)); + break; + case funky_mode: + XDrawString(display, window, fgc, 50, offset, funky_explanation, + strlen(funky_explanation)); + break; + case circle_mode: + XDrawString(display, window, fgc, 50, offset, circle_explanation, + strlen(circle_explanation)); + break; + case linear_mode: + XDrawString(display, window, fgc, 50, offset, linear_explanation, + strlen(linear_explanation)); + break; + case test_mode: + XDrawString(display, window, fgc, 50, offset, test_explanation, + strlen(test_explanation)); + break; + case fun_mode: + XDrawString(display, window, fgc, 50, offset, fun_explanation, + strlen(fun_explanation)); + break; + case innie_mode: + XDrawString(display, window, fgc, 50, offset, innie_explanation, + strlen(innie_explanation)); + break; + case lissajous_mode: + XDrawString(display, window, fgc, 50, offset, lissajous_explanation, + strlen(linear_explanation)); + } +} + static void funky(unsigned long int the_time, struct info *info, int pos[], int index) { @@ -351,8 +382,15 @@ screenhack (Display *display, Window window) /* The following are all X related toys */ XGCValues gcv; /* The structure to hold the GC data */ XWindowAttributes xgwa; /* A structure to hold window data */ + Pixmap b=0, ba=0; /* double-buffer to reduce flicker */ +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer backb = 0; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + GC fgc, bgc; int screen; + Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean"); + Bool dbeclear_p = get_boolean_resource ("useDBEClear", "Boolean"); unsigned long int current_time = 0; /* The global int telling the current time */ unsigned long int start_time = current_time; @@ -369,11 +407,35 @@ screenhack (Display *display, Window window) /* Set up the X toys that I will be using later */ screen = DefaultScreen(display); XGetWindowAttributes (display, window, &xgwa); + if (dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (dbeclear_p) + b = xdbe_get_backbuffer (display, window, XdbeBackground); + else + b = xdbe_get_backbuffer (display, window, XdbeUndefined); + backb = b; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + if (!b) + { + ba = XCreatePixmap (display, window, xgwa.width, xgwa.height,xgwa.depth); + b = ba; + } + } + else + { + b = window; + } + gcv.foreground = get_pixel_resource("foreground", "Foreground", display, xgwa.colormap); - fgc = XCreateGC (display, window, GCForeground, &gcv); + fgc = XCreateGC (display, b, GCForeground, &gcv); gcv.foreground = get_pixel_resource("background", "Background", display, xgwa.colormap); - bgc = XCreateGC (display, window, GCForeground, &gcv); + bgc = XCreateGC (display, b, GCForeground, &gcv); make_uniform_colormap (display, xgwa.visual, xgwa.colormap, colors, &ncolors, True, &info->writable, True); + + if (ba) XFillRectangle (display, ba, bgc, 0, 0, xgwa.width, xgwa.height); + /* info is a structure holding all the random pieces of information I may want to pass to my baby functions -- much of it I may never use, but it is nice to have around just in case I want it to make a funky function funkier */ @@ -395,26 +457,28 @@ screenhack (Display *display, Window window) xmode_str = get_string_resource("xmode", "Mode"); ymode_str = get_string_resource("ymode", "Mode"); wrap = get_integer_resource("wrap", "Integer"); - modifier = 3000.0 + (1500.0 * random() / (RAND_MAX + 1.0)); + modifier = 3000.0 + frand(1500.0); if (! xmode_str) xmode = spin_mode; else if (! strcmp (xmode_str, "spin")) xmode = spin_mode; else if (! strcmp (xmode_str, "funky")) xmode = funky_mode; + else if (! strcmp (xmode_str, "circle")) xmode = circle_mode; else if (! strcmp (xmode_str, "linear")) xmode = linear_mode; + else if (! strcmp (xmode_str, "test")) xmode = test_mode; else if (! strcmp (xmode_str, "fun")) xmode = fun_mode; else if (! strcmp (xmode_str, "innie")) xmode = innie_mode; else if (! strcmp (xmode_str, "lissajous")) xmode = lissajous_mode; - else if (! strcmp (xmode_str, "test")) xmode = test_mode; else { xmode = spin_mode; } if (! ymode_str) ymode = spin_mode; else if (! strcmp (ymode_str, "spin")) ymode = spin_mode; else if (! strcmp (ymode_str, "funky")) ymode = funky_mode; + else if (! strcmp (ymode_str, "circle")) ymode = circle_mode; else if (! strcmp (ymode_str, "linear")) ymode = linear_mode; + else if (! strcmp (ymode_str, "test")) ymode = test_mode; else if (! strcmp (ymode_str, "fun")) ymode = fun_mode; else if (! strcmp (ymode_str, "innie")) ymode = innie_mode; else if (! strcmp (ymode_str, "lissajous")) ymode = lissajous_mode; - else if (! strcmp (ymode_str, "test")) ymode = test_mode; else { ymode = spin_mode; } @@ -424,14 +488,14 @@ screenhack (Display *display, Window window) else current_time = get_integer_resource("start_time", "Integer"); if (info->whirlies == -1) - info->whirlies = 1 + (int)(15.0 * random() / (RAND_MAX + 1.0)); + info->whirlies = 1 + (random() % 15); if (info->nlines == -1) - info->nlines = 1 + (int)(5.0 * random() / (RAND_MAX + 1.0)); + info->nlines = 1 + (random() % 5); if (info->color_modifier == -1) - info->color_modifier = 1 + (int)(25.0 * random() / (RAND_MAX + 1.0)); - if (get_integer_resource("explain", "Integer") == 1) - explain(mode, info, display, window, fgc); - current_color = 1 + (int)((double)NCOLORS * random() / (RAND_MAX + 1.0)); + info->color_modifier = 1 + (random() % 25); + if (get_boolean_resource("explain", "Integer")) + explain(xmode, ymode, info, display, window, fgc); + current_color = 1 + (random() % NCOLORS); /* Now that info is full, lets play! */ while (1) { @@ -441,20 +505,20 @@ screenhack (Display *display, Window window) if (! strcmp (xmode_str, "change") && ! strcmp (ymode_str, "change")) { if ((current_time - start_time) > change_time) { start_time = current_time; - xmode = 1 + (int)(4.0 * random() / (RAND_MAX + 1.0)); - ymode = 1 + (int)(4.0 * random() / (RAND_MAX + 1.0)); + xmode = 1 + (random() % 4); + ymode = 1 + (random() % 4); } } else if (! strcmp (xmode_str, "change")) { if ((current_time - start_time) > change_time) { start_time = current_time; - xmode = 1 + (int)(3.5 * random() / (RAND_MAX + 1.0)); + xmode = 1 + (random() % 4); } } else if (! strcmp (ymode_str, "change")) { if ((current_time - start_time) > change_time) { start_time = current_time; - ymode = 1 + (int)(3.0 * random() / (RAND_MAX + 1.0)); + ymode = 1 + (random() % 3); printf("Changing ymode to %d\n", ymode); } } @@ -470,8 +534,9 @@ screenhack (Display *display, Window window) /* I want the distance between whirlies to increase more each whirly */ internal_time = current_time + (10 * wcount) + (wcount * wcount); switch (xmode) { - /* All these functions expect an int time, the struct info, a pointer to an array of positions, - and the index that the the function will fill of the array */ + /* All these functions expect an int time, the struct info, + a pointer to an array of positions, and the index that the + the function will fill of the array */ case spin_mode: spin(internal_time, info, pos, 0); break; @@ -534,10 +599,14 @@ screenhack (Display *display, Window window) double line_offset = 20.0 * (double)lcount * sin(arg); int size; size = (int)(15.0 + 5.0 * sin((double)internal_time / 180.0)); -/* First delete the old circle... */ - if (! info->trail) { + /* First delete the old circle... */ + if (!info->trail && ( !dbeclear_p || +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + !backb +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + )) { XSetForeground(display, bgc, BlackPixel(display, screen)); - XFillArc(display, window, bgc, last_x[wcount][lcount], last_y[wcount][lcount], last_size[wcount][lcount], last_size[wcount][lcount], START_ARC, END_ARC); + XFillArc(display, b, bgc, last_x[wcount][lcount], last_y[wcount][lcount], last_size[wcount][lcount], last_size[wcount][lcount], START_ARC, END_ARC); } /* Now, lets draw in the new circle */ { /* Starting new scope for local x_pos and y_pos */ @@ -551,7 +620,12 @@ screenhack (Display *display, Window window) ypos = (int)(info->yoffset*line_offset)+pos[1]; } if (start_time == current_time) { - /* smoothen should move from one mode to another prettily... */ + /* smoothen should move from one mode to another prettily... */ + + /* Note: smoothen has not been modified to take the double + buffering code into account, and needs to be hacked on + before uncommenting. + */ /* smoothen(xpos, last_x[wcount][lcount], ypos, last_y[wcount][lcount], size, color_offset, colors, display, window, bgc, screen, info); */ @@ -560,10 +634,29 @@ screenhack (Display *display, Window window) last_y[wcount][lcount] = ypos; last_size[wcount][lcount] = size; XSetForeground(display, bgc, colors[color_offset].pixel); - XFillArc(display, window, bgc, xpos, ypos, size, size, START_ARC, END_ARC); + XFillArc(display, b, bgc, xpos, ypos, size, size, START_ARC, END_ARC); } /* End of my temporary scope for xpos and ypos */ } /* End of the for each line in nlines */ } /* End of the for each whirly in whirlies */ + + + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = window; + info[0].swap_action = (dbeclear_p ? XdbeBackground : XdbeUndefined); + XdbeSwapBuffers (display, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (dbuf) + { + XCopyArea (display, b, window, bgc, 0, 0, + xgwa.width, xgwa.height, 0, 0); + } + XSync(display, False); if (current_time == FULL_CYCLE) current_time = 1;