X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Flisa.c;h=1972389c866ab09a1b2c10f072ff8bda0a6f0983;hp=a45e75ee4325a9cde68fa68262daab8d65385832;hb=c494fd2e6b3b25582375d62e40f4f5cc984ca424;hpb=07faf451b99879183ed7e909e43a0e065be1ee7f diff --git a/hacks/lisa.c b/hacks/lisa.c index a45e75ee..1972389c 100644 --- a/hacks/lisa.c +++ b/hacks/lisa.c @@ -6,7 +6,7 @@ static const char sccsid[] = "@(#)lisa.c 5.00 2000/11/01 xlockmore"; #endif /*- - * Copyright (c) 1997 by Caleb Cullen. + * Copyright (c) 1997, 2006 by Caleb Cullen. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, @@ -21,6 +21,7 @@ static const char sccsid[] = "@(#)lisa.c 5.00 2000/11/01 xlockmore"; * other special, indirect and consequential damages. * * Revision History: + * 23-Feb-2006: fixed color-cycling issues * 01-Nov-2000: Allocation checks * 10-May-1997: Compatible with xscreensaver * @@ -33,21 +34,36 @@ static const char sccsid[] = "@(#)lisa.c 5.00 2000/11/01 xlockmore"; * The `lissie' module's source code was studied as an example of how * to incorporate a new module into xlock. Resemblances to it are * expected, but not intended to be plaigiaristic. + * + * February, 2006: 21st Century Update for Lisa + * + fixed color-mapping: the 'beginning' of the loop always uses the + * same (starting) pixel value, causing the loop's coloration to + * appear solid rather than flickering as in the previous version + * + all lines/points in a single color are drawn at once using XDrawLines() + * or XDrawPoints(); the artifacting evident in the previous version + * has been masked by the use of CapNotLast to separate individual drawn + * areas with intentional "whitespace" (typically black) + * + added many new elements to the Function[] array + * + randomized selection of next function + * + introduced concept of "rarely-chosen" functions + * + cleaned up code somewhat, standardized capitalization, commented all + * #directives with block labels */ #ifdef STANDALONE # define MODE_lisa -# define DEFAULTS "*delay: 25000 \n" \ +# define DEFAULTS "*delay: 17000 \n" \ "*count: 1 \n" \ - "*cycles: 256 \n" \ + "*cycles: 768 \n" \ "*size: -1 \n" \ - "*ncolors: 200 \n" + "*ncolors: 64 \n" # define UNIFORM_COLORS # define reshape_lisa 0 # define lisa_handle_event 0 # include "xlockmore.h" /* in xscreensaver distribution */ #else /* STANDALONE */ -# include "xlock.h" /* in xlockmore distribution */ +#include "xlock.h" /* in xlockmore distribution */ + #endif /* STANDALONE */ #ifdef MODE_lisa @@ -79,32 +95,49 @@ ENTRYPOINT ModeSpecOpt lisa_opts = ModStruct lisa_description = {"lisa", "init_lisa", "draw_lisa", "release_lisa", "refresh_lisa", "change_lisa", (char *) NULL, &lisa_opts, - 25000, 1, 256, -1, 64, 1.0, "", - "Shows animated lisajous loops", 0, NULL}; + 17000, 1, 768, -1, 64, 1.0, "", + "Shows animated lisajous figures", 0, NULL}; #endif #define DRAWLINES 1 +/* #define FOLLOW_FUNC_ORDER 1 */ #define TWOLOOPS 1 #define XVMAX 10 /* Maximum velocities */ #define YVMAX 10 #define LISAMAXFUNCS 2 -#define NUMSTDFUNCS 10 +#define NUMSTDFUNCS 28 +#define RAREFUNCMIN 25 +#define RAREFUNCODDS 4 /* 1:n chance a rare function will be re-randomized */ #define MAXCYCLES 3 #define MINLISAS 1 -#define lisasetcolor() \ -if (MI_NPIXELS(mi) > 2) { \ - XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_PIXEL(mi, loop->color)); \ - if (++(loop->color) >= (unsigned) MI_NPIXELS(mi)) { loop->color=0; } \ - } else { XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); } -#define getRadius(context) \ - ((context->width > context->height)?context->height:context->width) * 3 / 8 -#define checkRadius(loop, context) \ - if ((context->height / 2 > MI_SIZE(mi)) && (context->width / 2 > MI_SIZE(mi))) \ - loop->radius = MI_SIZE(mi); \ - if ((loop->radius < 0) || \ - (loop->radius > loop->center.x) || \ - (loop->radius > loop->center.y)) loop->radius = getRadius(context) +#define STARTCOLOR 0 +#define STARTFUNC 24 /* if negative, is upper-bound on randomization */ +#define LINEWIDTH -8 /* if negative, is upper-bound on randomization */ +#define LINESTYLE LineSolid /* an insane man might have fun with this :) */ +#define LINECAP CapNotLast /* anything else looks pretty crappy */ +#define LINEJOIN JoinBevel /* this ought to be fastest */ +#define SET_COLOR() \ + if (MI_NPIXELS(mi) > 2) { \ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_PIXEL(mi, loop->color)); \ + if (loop->cstep \ + && pctr % loop->cstep == 0 \ + && ++(loop->color) >= (unsigned) MI_NPIXELS(mi)) \ + { loop->color=STARTCOLOR; } \ + } else { XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi)); } +#define GET_RADIUS(context) \ + ((context->width > context->height)?context->height:context->width) * 3 / 8 +#define CHECK_RADIUS(loop, context) \ + if ((context->height / 2 > MI_SIZE(mi)) && (context->width / 2 > MI_SIZE(mi))) \ + loop->radius = MI_SIZE(mi); \ + if ((loop->radius < 0) || \ + (loop->radius > loop->center.x) || \ + (loop->radius > loop->center.y)) loop->radius = GET_RADIUS(context) +#define PRINT_FUNC(funcptr) \ + printf("new function -- #%d:\n\tx = sin(%gs) * sin(%gs)\n\ty = sin(%gt) * sin(%gt)\n", \ + funcptr->index, \ + funcptr->xcoeff[0], funcptr->xcoeff[1], \ + funcptr->ycoeff[0], funcptr->ycoeff[1]) typedef struct lisafunc_struct { @@ -114,12 +147,12 @@ typedef struct lisafunc_struct { } lisafuncs; typedef struct lisa_struct { - unsigned long color; - int radius, dx, dy, nsteps, nfuncs, melting; - double pistep, phi, theta; - XPoint center, *lastpoint; - lisafuncs *function[LISAMAXFUNCS]; - int linewidth; + unsigned long color; + int radius, dx, dy, nsteps, nfuncs, melting, cstep; + double pistep, phi, theta; + XPoint center, *lastpoint; + lisafuncs *function[LISAMAXFUNCS]; + int linewidth; } lisas; typedef struct lisacontext_struct { @@ -132,39 +165,95 @@ typedef struct lisacontext_struct { static lisacons *Lisa = (lisacons *) NULL; static lisafuncs Function[NUMSTDFUNCS] = -{ + { + { + {1.0, 2.0}, + {1.0, 2.0}, 2, 2, 0}, + { + {1.0, 2.0}, + {1.0, 1.0}, 2, 2, 1}, + { + {1.0, 3.0}, + {1.0, 2.0}, 2, 2, 2}, + { + {1.0, 3.0}, + {1.0, 3.0}, 2, 2, 3}, + { + {2.0, 4.0}, + {1.0, 2.0}, 2, 2, 4}, + { + {1.0, 4.0}, + {1.0, 3.0}, 2, 2, 5}, + { + {1.0, 4.0}, + {1.0, 4.0}, 2, 2, 6}, + { + {1.0, 5.0}, + {1.0, 5.0}, 2, 2, 7}, + { + {2.0, 5.0}, + {2.0, 5.0}, 2, 2, 8}, + { + {1.0, 2.0}, + {2.0, 5.0}, 2, 2, 9}, + { + {1.0, 2.0}, + {3.0, 5.0}, 2, 2, 10}, + { + {1.0, 2.0}, + {2.0, 3.0}, 2, 2, 11}, { - {1.0, 2.0}, - {1.0, 2.0}, 2, 2, 0}, + {1.0, 3.0}, + {2.0, 3.0}, 2, 2, 12}, { - {1.0, 2.0}, - {1.0, 1.0}, 2, 2, 1}, + {2.0, 3.0}, + {1.0, 3.0}, 2, 2, 13}, { - {1.0, 3.0}, - {1.0, 2.0}, 2, 2, 2}, + {2.0, 4.0}, + {1.0, 3.0}, 2, 2, 14}, { - {1.0, 3.0}, - {1.0, 3.0}, 2, 2, 3}, + {1.0, 4.0}, + {2.0, 3.0}, 2, 2, 15}, { - {2.0, 4.0}, - {1.0, 2.0}, 2, 2, 4}, + {2.0, 4.0}, + {2.0, 3.0}, 2, 2, 16}, { - {1.0, 4.0}, - {1.0, 3.0}, 2, 2, 5}, + {1.0, 5.0}, + {2.0, 3.0}, 2, 2, 17}, { - {1.0, 4.0}, - {1.0, 4.0}, 2, 2, 6}, + {2.0, 5.0}, + {2.0, 3.0}, 2, 2, 18}, { - {1.0, 5.0}, - {1.0, 5.0}, 2, 2, 7}, + {1.0, 5.0}, + {2.0, 5.0}, 2, 2, 19}, { - {2.0, 5.0}, - {2.0, 5.0}, 2, 2, 8}, + {1.0, 3.0}, + {2.0, 7.0}, 2, 2, 20}, { - {1.0, 0.0}, - {1.0, 0.0}, 1, 1, 9} + {2.0, 3.0}, + {5.0, 7.0}, 2, 2, 21}, + { + {1.0, 2.0}, + {3.0, 7.0}, 2, 2, 22}, + { + {2.0, 5.0}, + {5.0, 7.0}, 2, 2, 23}, + { + {5.0, 7.0}, + {5.0, 7.0}, 2, 2, 24}, + { /* functions past here are 'rare' and won't */ + {2.0, 7.0}, /* show up as often. tweak the #defines above */ + {1.0, 7.0}, 2, 2, 25}, /* to see them more frequently */ + { + {2.0, 9.0}, + {1.0, 7.0}, 2, 2, 26}, + { + {5.0, 11.0}, + {2.0, 9.0}, 2, 2, 27} }; +int xMaxLines; + static void free_lisa(lisacons *lc) { @@ -187,11 +276,14 @@ drawlisa(ModeInfo * mi, lisas * loop) lisacons *lc = &Lisa[MI_SCREEN(mi)]; lisafuncs **lf = loop->function; int phase = lc->loopcount % loop->nsteps; - int pctr, fctr, xctr, yctr; + int pctr, fctr, xctr, yctr, extra_points; double xprod, yprod, xsum, ysum; - /* Allocate the np array */ - if ((np = (XPoint *) calloc(loop->nsteps, sizeof (XPoint))) == NULL) { + /* why carry this around in the struct when we can calculate it on demand? */ + extra_points = loop->cstep - (loop->nsteps % loop->cstep); + + /* Allocate the np (new point) array (with padding) */ + if ((np = (XPoint *) calloc(loop->nsteps+extra_points, sizeof (XPoint))) == NULL) { free_lisa(lc); return False; } @@ -199,7 +291,10 @@ drawlisa(ModeInfo * mi, lisas * loop) /* Update the center */ loop->center.x += loop->dx; loop->center.y += loop->dy; - checkRadius(loop, lc); + CHECK_RADIUS(loop, lc); + + /* check for overlaps -- where the figure might go off the screen */ + if ((loop->center.x - loop->radius) <= 0) { loop->center.x = loop->radius; loop->dx = NRAND(XVMAX); @@ -280,48 +375,91 @@ drawlisa(ModeInfo * mi, lisas * loop) np[pctr].x = (int) ceil(xsum); np[pctr].y = (int) ceil(ysum); } + /* fill in extra points */ + for (pctr=loop->nsteps; pctr < loop->nsteps+extra_points; pctr++) { + np[pctr].x = np[pctr - loop->nsteps].x; + np[pctr].y = np[pctr - loop->nsteps].y; + } if (loop->melting) { if (!--loop->melting) { loop->nfuncs = 1; loop->function[0] = loop->function[1]; } } - for (pctr = 0; pctr < loop->nsteps; pctr++) { + /* reset starting color each time to prevent ass-like appearance */ + loop->color = STARTCOLOR; + + if (loop->cstep < xMaxLines) { + /* printf("Drawing dashes\n"); */ + for (pctr = 0; pctr < loop->nsteps; pctr+=loop->cstep) { #if defined DRAWLINES XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, - LineSolid, CapProjecting, JoinMiter); + LINESTYLE, LINECAP, LINEJOIN); /* erase the last cycle's point */ XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); - XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), - MI_GC(mi), lp[pctr].x, lp[pctr].y, - lp[(pctr + 1) % loop->nsteps].x, - lp[(pctr + 1) % loop->nsteps].y); + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), &lp[pctr], + loop->cstep, CoordModeOrigin); /* Set the new color */ - lisasetcolor(); + SET_COLOR(); /* plot this cycle's point */ - XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), - MI_GC(mi), np[pctr].x, np[pctr].y, - np[(pctr + 1) % loop->nsteps].x, - np[(pctr + 1) % loop->nsteps].y); + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &np[pctr], loop->cstep, CoordModeOrigin); XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, - LineSolid, CapProjecting, JoinMiter); + LINESTYLE, LINECAP, LINEJOIN); #else /* erase the last cycle's point */ XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); - XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), - MI_GC(mi), lp[pctr].x, lp[pctr].y); + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &lp[pctr], loop->cstep, CoordModeOrigin); /* Set the new color */ - lisasetcolor(); + SET_COLOR(); /* plot this cycle's point */ - XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), - MI_GC(mi), np[pctr].x, np[pctr].y); + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), &np[pctr], loop->cstep, CoordModeOrigin); #endif } + } else { /* on my system, cstep is larger than 65532/2 if we get here */ + for (pctr = 0; pctr < loop->nsteps; pctr++) { +#if defined DRAWLINES + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, + LINESTYLE, LINECAP, LINEJOIN); + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), lp[pctr].x, lp[pctr].y, + lp[(pctr + 1) % loop->nsteps].x, + lp[(pctr + 1) % loop->nsteps].y); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), np[pctr].x, np[pctr].y, + np[(pctr + 1) % loop->nsteps].x, + np[(pctr + 1) % loop->nsteps].y); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, + LINESTYLE, LINECAP, LINEJOIN); +#else /* DRAWLINES */ + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), lp[pctr].x, lp[pctr].y); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), np[pctr].x, np[pctr].y); +#endif /* DRAWLINES */ + } + } (void) free((void *) lp); loop->lastpoint = np; return True; @@ -330,95 +468,137 @@ drawlisa(ModeInfo * mi, lisas * loop) static Bool initlisa(ModeInfo * mi, lisas * loop) { - lisacons *lc = &Lisa[MI_SCREEN(mi)]; - lisafuncs **lf = loop->function; - XPoint *lp; - int phase, pctr, fctr, xctr, yctr; - double xprod, yprod, xsum, ysum; - - if (MI_NPIXELS(mi) > 2) { - loop->color = 0; - } else - loop->color = MI_WHITE_PIXEL(mi); - loop->nsteps = MI_CYCLES(mi); - if (loop->nsteps == 0) - loop->nsteps = 1; - lc->maxcycles = (MAXCYCLES * loop->nsteps) - 1; - loop->melting = 0; - loop->nfuncs = 1; - loop->pistep = 2.0 * M_PI / (double) loop->nsteps; - loop->center.x = lc->width / 2; - loop->center.y = lc->height / 2; - loop->radius = (int) MI_SIZE(mi); - checkRadius(loop, lc); - loop->dx = NRAND(XVMAX); - loop->dy = NRAND(YVMAX); - loop->dx++; - loop->dy++; - lf[0] = &Function[lc->loopcount % NUMSTDFUNCS]; - if ((lp = loop->lastpoint = (XPoint *) - calloc(loop->nsteps, sizeof (XPoint))) == NULL) { - free_lisa(lc); - return False; + lisacons *lc = &Lisa[MI_SCREEN(mi)]; + lisafuncs **lf = loop->function; + XPoint *lp; + int phase, pctr, fctr, xctr, yctr, extra_points; + double xprod, yprod, xsum, ysum; + + xMaxLines = (XMaxRequestSize(MI_DISPLAY(mi))-3)/2; + /* printf("Got xMaxLines = %d\n", xMaxLines); */ + loop->nsteps = MI_CYCLES(mi); + if (loop->nsteps == 0) + loop->nsteps = 1; + if (MI_NPIXELS(mi) > 2) { + loop->color = STARTCOLOR; + loop->cstep = (loop->nsteps > MI_NPIXELS(mi)) ? loop->nsteps / MI_NPIXELS(mi) : 1; + } else { + loop->color = MI_WHITE_PIXEL(mi); + loop->cstep = 0; + } + extra_points = loop->cstep - (loop->nsteps % loop->cstep); + lc->maxcycles = (MAXCYCLES * loop->nsteps) - 1; + loop->cstep = ( loop->nsteps > MI_NPIXELS(mi) ) ? loop->nsteps / MI_NPIXELS(mi) : 1; + /* printf("Got cstep = %d\n", loop->cstep); */ + loop->melting = 0; + loop->nfuncs = 1; + loop->pistep = 2.0 * M_PI / (double) loop->nsteps; + loop->center.x = lc->width / 2; + loop->center.y = lc->height / 2; + loop->radius = (int) MI_SIZE(mi); + CHECK_RADIUS(loop, lc); + loop->dx = NRAND(XVMAX); + loop->dy = NRAND(YVMAX); + loop->dx++; + loop->dy++; +#if defined STARTFUNC + lf[0] = &Function[STARTFUNC]; +#else /* STARTFUNC */ + lf[0] = &Function[NRAND(NUMSTDFUNCS)]; +#endif /* STARTFUNC */ + + if ((lp = loop->lastpoint = (XPoint *) + calloc(loop->nsteps+extra_points, sizeof (XPoint))) == NULL) { + free_lisa(lc); + return False; + } + phase = lc->loopcount % loop->nsteps; + +#if defined DEBUG + printf( "nsteps = %d\tcstep = %d\tmrs = %d\textra_points = %d\n", + loop->nsteps, loop->cstep, xMaxLines, extra_points ); + PRINT_FUNC(lf[0]); +#endif /* DEBUG */ + + for (pctr = 0; pctr < loop->nsteps; pctr++) { + loop->phi = (double) (pctr - phase) * loop->pistep; + loop->theta = (double) (pctr + phase) * loop->pistep; + fctr = loop->nfuncs; + xsum = ysum = 0.0; + while (fctr--) { + xprod = yprod = (double) loop->radius; + xctr = lf[fctr]->nx; + yctr = lf[fctr]->ny; + while (xctr--) + xprod *= sin(lf[fctr]->xcoeff[xctr] * loop->theta); + while (yctr--) + yprod *= sin(lf[fctr]->ycoeff[yctr] * loop->phi); + xsum += xprod; + ysum += yprod; } - phase = lc->loopcount % loop->nsteps; - - for (pctr = 0; pctr < loop->nsteps; pctr++) { - loop->phi = (double) (pctr - phase) * loop->pistep; - loop->theta = (double) (pctr + phase) * loop->pistep; - fctr = loop->nfuncs; - xsum = ysum = 0.0; - while (fctr--) { - xprod = yprod = (double) loop->radius; - xctr = lf[fctr]->nx; - yctr = lf[fctr]->ny; - while (xctr--) - xprod *= sin(lf[fctr]->xcoeff[xctr] * loop->theta); - while (yctr--) - yprod *= sin(lf[fctr]->ycoeff[yctr] * loop->phi); - xsum += xprod; - ysum += yprod; - } - if (loop->nfuncs > 1) { - xsum /= 2.0; - ysum /= 2.0; - } - xsum += (double) loop->center.x; - ysum += (double) loop->center.y; - - lp[pctr].x = (int) ceil(xsum); - lp[pctr].y = (int) ceil(ysum); + if (loop->nfuncs > 1) { + xsum /= 2.0; + ysum /= 2.0; } + xsum += (double) loop->center.x; + ysum += (double) loop->center.y; + + lp[pctr].x = (int) ceil(xsum); + lp[pctr].y = (int) ceil(ysum); + } + /* this fills in the extra points, so we can use segment-drawing calls */ + for (pctr = loop->nsteps; pctr < loop->nsteps + extra_points; pctr++) { + lp[pctr].x=lp[pctr - loop->nsteps].x; + lp[pctr].y=lp[pctr - loop->nsteps].y; + } #if defined DRAWLINES - { - loop->linewidth = -8; /* #### make this a resource */ - - if (loop->linewidth == 0) - loop->linewidth = 1; - if (loop->linewidth < 0) - loop->linewidth = NRAND(-loop->linewidth) + 1; - XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, - LineSolid, CapProjecting, JoinMiter); + loop->linewidth = LINEWIDTH; /* #### make this a resource */ + + if (loop->linewidth == 0) + loop->linewidth = 1; + if (loop->linewidth < 0) + loop->linewidth = NRAND(-loop->linewidth) + 1; + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, + LINESTYLE, LINECAP, LINEJOIN); +#endif /* DRAWLINES */ + + if ( loop->cstep < xMaxLines ) { + /* we can send each color segment in a single request + * because the max request length is long enough + * and because we have padded out the array to have extra elements + * to support calls which would otherwise fall off the end*/ + for (pctr = 0; pctr < loop->nsteps; pctr+=loop->cstep) { + /* Set the color */ + SET_COLOR(); + +#if defined DRAWLINES + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), + MI_GC(mi), &lp[pctr], loop->cstep, CoordModeOrigin ); +#else /* DRAWLINES */ + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &lp[pctr], loop->cstep, CoordModeOrigin ); +#endif /* DRAWLINES */ } -#endif - for (pctr = 0; pctr < loop->nsteps; pctr++) { - /* Set the color */ - lisasetcolor(); + } else { /* do it one by one as before */ + for (pctr = 0; pctr < loop->nsteps; pctr++ ) { + SET_COLOR(); + #if defined DRAWLINES - XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), - MI_GC(mi), lp[pctr].x, lp[pctr].y, - lp[(pctr + 1) % loop->nsteps].x, - lp[(pctr + 1) % loop->nsteps].y); -#else - XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), - lp[pctr].x, lp[pctr].y); -#endif + XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + lp[pctr].x, lp[pctr].y, + lp[pctr+1 % loop->nsteps].x, lp[pctr+1 % loop->nsteps].y); +#else /* DRAWLINES */ + XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + lp[pctr].x, lp[pctr].y); +#endif /* DRAWLINES */ } + } + #if defined DRAWLINES - XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, - LineSolid, CapProjecting, JoinMiter); -#endif - return True; + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, + LINESTYLE, LINECAP, LINEJOIN); +#endif /* DRAWLINES */ + return True; } static void @@ -455,7 +635,7 @@ static void change_lisa(ModeInfo * mi) { lisas *loop; - int lctr; + int lctr, newfunc; lisacons *lc; if (Lisa == NULL) @@ -466,12 +646,31 @@ change_lisa(ModeInfo * mi) lc->loopcount = 0; for (lctr = 0; lctr < lc->nlisajous; lctr++) { - loop = &lc->lisajous[lctr]; - loop->function[1] = &Function[(loop->function[0]->index + 1) % - NUMSTDFUNCS]; - loop->melting = loop->nsteps - 1; - loop->nfuncs = 2; + loop = &lc->lisajous[lctr]; /* count through the loops we're drawing */ + newfunc = NRAND(NUMSTDFUNCS); /* choose a new function at random */ +#if defined FOLLOW_FUNC_ORDER + loop->function[1] = + &Function[(loop->function[0]->index + 1) % NUMSTDFUNCS]; +#else /* FOLLOW_FUNC_ORDER */ + if (newfunc == loop->function[0]->index) { + ++newfunc; + newfunc %= NUMSTDFUNCS; /* take the next if we got the one we have */ + } + if (newfunc >= RAREFUNCMIN \ + && !(random() % RAREFUNCODDS) \ + && (newfunc = NRAND(NUMSTDFUNCS)) == loop->function[0]->index) { + ++newfunc; + newfunc %= NUMSTDFUNCS; } + loop->function[1] = /* set 2nd function pointer on the loop */ + &Function[newfunc]; /* to the new function we just chose */ +#endif /* FOLLOW_FUNC_ORDER */ +#if defined DEBUG + PRINT_FUNC(loop->function[1]); +#endif /* DEBUG */ + loop->melting = loop->nsteps - 1; /* melt the two functions together */ + loop->nfuncs = 2; /* simultaneously for a full cycle */ + } } ENTRYPOINT void