X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Flisa.c;h=1a1159f62cdfadc9d4840033b6801d98d2b89497;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hp=235ceab9b187840ddd40a666fe1db765feb4c984;hpb=96a411663168b0ba5432b407a83be55f3df0c802;p=xscreensaver diff --git a/hacks/lisa.c b/hacks/lisa.c index 235ceab9..1a1159f6 100644 --- a/hacks/lisa.c +++ b/hacks/lisa.c @@ -1,12 +1,12 @@ /* -*- Mode: C; tab-width: 4 -*- */ -/* lisa --- animated full-loop lisajous figures */ +/* lisa --- animated full-loop lissajous figures */ #if 0 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,36 +21,50 @@ 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 * * The inspiration for this program, Lasp, was written by Adam B. Roach * in 1990, assisted by me, Caleb Cullen. It was written first in C, then - * in assembly, and used pre-calculated data tables to graph lisajous + * in assembly, and used pre-calculated data tables to graph lissajous * figures on 386 machines and lower. This version bears only superficial * resemblances to the original Lasp. * * 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 PROGCLASS "Lisa" -#define HACK_INIT init_lisa -#define HACK_DRAW draw_lisa -#define lisa_opts xlockmore_opts -#define DEFAULTS "*delay: 25000 \n" \ - "*count: 1 \n" \ - "*cycles: 256 \n" \ - "*size: -1 \n" \ - "*ncolors: 200 \n" -#define UNIFORM_COLORS -#include "xlockmore.h" /* in xscreensaver distribution */ - +# define MODE_lisa +# define DEFAULTS "*delay: 17000 \n" \ + "*count: 1 \n" \ + "*cycles: 768 \n" \ + "*size: 500 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \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 */ @@ -62,53 +76,70 @@ static Bool additive; static XrmOptionDescRec opts[] = { - {(char *) "-additive", (char *) ".lisa.additive", XrmoptionNoArg, (caddr_t) "True"}, - {(char *) "+additive", (char *) ".lisa.additive", XrmoptionNoArg, (caddr_t) "False"} + {"-additive", ".lisa.additive", XrmoptionNoArg, "True"}, + {"+additive", ".lisa.additive", XrmoptionNoArg, "False"} }; static argtype vars[] = { - {(caddr_t *) & additive, (char *) "additive", (char *) "Additive", (char *) DEF_ADDITIVE, t_Bool} + {&additive, "additive", "Additive", DEF_ADDITIVE, t_Bool} }; static OptionStruct desc[] = { - {(char *) "-/+additive", (char *) "turn on/off additive functions mode"} + {"-/+additive", "turn on/off additive functions mode"} }; -ModeSpecOpt lisa_opts = +ENTRYPOINT ModeSpecOpt lisa_opts = {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; #ifdef USE_MODULES 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 lissajous 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 { @@ -118,17 +149,17 @@ 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 { - lisas *lisajous; - int width, height, nlisajous, loopcount; + lisas *lissajous; + int width, height, nlissajous, loopcount; int maxcycles; Bool painted; } lisacons; @@ -136,50 +167,106 @@ 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, 3.0}, + {2.0, 3.0}, 2, 2, 12}, + { + {2.0, 3.0}, + {1.0, 3.0}, 2, 2, 13}, { - {1.0, 2.0}, - {1.0, 2.0}, 2, 2, 0}, + {2.0, 4.0}, + {1.0, 3.0}, 2, 2, 14}, { - {1.0, 2.0}, - {1.0, 1.0}, 2, 2, 1}, + {1.0, 4.0}, + {2.0, 3.0}, 2, 2, 15}, { - {1.0, 3.0}, - {1.0, 2.0}, 2, 2, 2}, + {2.0, 4.0}, + {2.0, 3.0}, 2, 2, 16}, { - {1.0, 3.0}, - {1.0, 3.0}, 2, 2, 3}, + {1.0, 5.0}, + {2.0, 3.0}, 2, 2, 17}, { - {2.0, 4.0}, - {1.0, 2.0}, 2, 2, 4}, + {2.0, 5.0}, + {2.0, 3.0}, 2, 2, 18}, { - {1.0, 4.0}, - {1.0, 3.0}, 2, 2, 5}, + {1.0, 5.0}, + {2.0, 5.0}, 2, 2, 19}, { - {1.0, 4.0}, - {1.0, 4.0}, 2, 2, 6}, + {1.0, 3.0}, + {2.0, 7.0}, 2, 2, 20}, { - {1.0, 5.0}, - {1.0, 5.0}, 2, 2, 7}, + {2.0, 3.0}, + {5.0, 7.0}, 2, 2, 21}, { - {2.0, 5.0}, - {2.0, 5.0}, 2, 2, 8}, + {1.0, 2.0}, + {3.0, 7.0}, 2, 2, 22}, { - {1.0, 0.0}, - {1.0, 0.0}, 1, 1, 9} + {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) { - while (lc->lisajous) { + while (lc->lissajous) { int lctr; - for (lctr = 0; lctr < lc->nlisajous; lctr++) { - (void) free((void *) lc->lisajous[lctr].lastpoint); + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + (void) free((void *) lc->lissajous[lctr].lastpoint); } - (void) free((void *) lc->lisajous); - lc->lisajous = (lisas *) NULL; + (void) free((void *) lc->lissajous); + lc->lissajous = (lisas *) NULL; } } @@ -191,11 +278,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; } @@ -203,7 +293,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); @@ -284,48 +377,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; @@ -334,95 +470,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 @@ -431,13 +609,13 @@ refreshlisa(ModeInfo * mi) lisacons *lc = &Lisa[MI_SCREEN(mi)]; int lctr; - for (lctr = 0; lctr < lc->nlisajous; lctr++) { - if (!drawlisa(mi, &lc->lisajous[lctr])) + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + if (!drawlisa(mi, &lc->lissajous[lctr])) return; } } -void +ENTRYPOINT void refresh_lisa(ModeInfo * mi) { lisacons *lc; @@ -445,7 +623,7 @@ refresh_lisa(ModeInfo * mi) if (Lisa == NULL) return; lc = &Lisa[MI_SCREEN(mi)]; - if (lc->lisajous == NULL) + if (lc->lissajous == NULL) return; if (lc->painted) { @@ -455,56 +633,71 @@ refresh_lisa(ModeInfo * mi) } } -void +static void change_lisa(ModeInfo * mi) { lisas *loop; - int lctr; + int lctr, newfunc; lisacons *lc; if (Lisa == NULL) return; lc = &Lisa[MI_SCREEN(mi)]; - if (lc->lisajous == NULL) + if (lc->lissajous == NULL) return; 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; + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + loop = &lc->lissajous[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 */ + } } -void -init_lisa(ModeInfo * mi) +ENTRYPOINT void +init_lisa (ModeInfo * mi) { int lctr; lisacons *lc; - if (Lisa == NULL) { - if ((Lisa = (lisacons *) calloc(MI_NUM_SCREENS(mi), - sizeof (lisacons))) == NULL) - return; - } + MI_INIT (mi, Lisa, 0); lc = &Lisa[MI_SCREEN(mi)]; lc->width = MI_WIDTH(mi); lc->height = MI_HEIGHT(mi); lc->loopcount = 0; - lc->nlisajous = MI_COUNT(mi); - if (lc->nlisajous <= 0) - lc->nlisajous = 1; + lc->nlissajous = MI_COUNT(mi); + if (lc->nlissajous <= 0) + lc->nlissajous = 1; MI_CLEARWINDOW(mi); lc->painted = False; - if (lc->lisajous == NULL) { - if ((lc->lisajous = (lisas *) calloc(lc->nlisajous, + if (lc->lissajous == NULL) { + if ((lc->lissajous = (lisas *) calloc(lc->nlissajous, sizeof (lisas))) == NULL) return; - for (lctr = 0; lctr < lc->nlisajous; lctr++) { - if (!initlisa(mi, &lc->lisajous[lctr])) + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + if (!initlisa(mi, &lc->lissajous[lctr])) return; lc->loopcount++; } @@ -513,17 +706,21 @@ init_lisa(ModeInfo * mi) } } -void -draw_lisa(ModeInfo * mi) +ENTRYPOINT void +draw_lisa (ModeInfo * mi) { lisacons *lc; if (Lisa == NULL) return; lc = &Lisa[MI_SCREEN(mi)]; - if (lc->lisajous == NULL) + if (lc->lissajous == NULL) return; +#ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */ + XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi)); +#endif + MI_IS_DRAWN(mi) = True; lc->painted = True; if (++lc->loopcount > lc->maxcycles) { @@ -532,8 +729,8 @@ draw_lisa(ModeInfo * mi) refreshlisa(mi); } -void -release_lisa(ModeInfo * mi) +ENTRYPOINT void +release_lisa (ModeInfo * mi) { if (Lisa) { int screen; @@ -545,4 +742,6 @@ release_lisa(ModeInfo * mi) } } +XSCREENSAVER_MODULE ("Lisa", lisa) + #endif /* MODE_lisa */