From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/lisa.c | 739 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 739 insertions(+) create mode 100644 hacks/lisa.c (limited to 'hacks/lisa.c') diff --git a/hacks/lisa.c b/hacks/lisa.c new file mode 100644 index 0000000..d0303b8 --- /dev/null +++ b/hacks/lisa.c @@ -0,0 +1,739 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* lisa --- animated full-loop lissajous figures */ + +#if 0 +static const char sccsid[] = "@(#)lisa.c 5.00 2000/11/01 xlockmore"; +#endif + +/*- + * 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, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * 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 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 DEFAULTS "*delay: 17000 \n" \ + "*count: 1 \n" \ + "*cycles: 768 \n" \ + "*size: 500 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + "*lowrez: True \n" \ + +# define UNIFORM_COLORS +# define release_lisa 0 +# define reshape_lisa 0 +# define lisa_handle_event xlockmore_no_events +# include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +#include "xlock.h" /* in xlockmore distribution */ + +#endif /* STANDALONE */ + +#ifdef MODE_lisa + +#define DEF_ADDITIVE "True" + +static Bool additive; + +static XrmOptionDescRec opts[] = +{ + {"-additive", ".lisa.additive", XrmoptionNoArg, "True"}, + {"+additive", ".lisa.additive", XrmoptionNoArg, "False"} +}; + +static argtype vars[] = +{ + {&additive, "additive", "Additive", DEF_ADDITIVE, t_Bool} +}; + +static OptionStruct desc[] = +{ + {"-/+additive", "turn on/off additive functions mode"} +}; + +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", (char *) NULL, + "refresh_lisa", "change_lisa", "free_lisa", &lisa_opts, + 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 28 +#define RAREFUNCMIN 25 +#define RAREFUNCODDS 4 /* 1:n chance a rare function will be re-randomized */ +#define MAXCYCLES 3 +#define MINLISAS 1 +#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 { + double xcoeff[2], ycoeff[2]; + int nx, ny; + int index; +} lisafuncs; + +typedef struct lisa_struct { + 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 *lissajous; + int width, height, nlissajous, loopcount; + int maxcycles; + Bool painted; +} lisacons; + +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}, + { + {2.0, 4.0}, + {1.0, 3.0}, 2, 2, 14}, + { + {1.0, 4.0}, + {2.0, 3.0}, 2, 2, 15}, + { + {2.0, 4.0}, + {2.0, 3.0}, 2, 2, 16}, + { + {1.0, 5.0}, + {2.0, 3.0}, 2, 2, 17}, + { + {2.0, 5.0}, + {2.0, 3.0}, 2, 2, 18}, + { + {1.0, 5.0}, + {2.0, 5.0}, 2, 2, 19}, + { + {1.0, 3.0}, + {2.0, 7.0}, 2, 2, 20}, + { + {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; + +ENTRYPOINT void +free_lisa(ModeInfo * mi) +{ + lisacons *lc = &Lisa[MI_SCREEN(mi)]; + while (lc->lissajous) { + int lctr; + + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + (void) free((void *) lc->lissajous[lctr].lastpoint); + } + (void) free((void *) lc->lissajous); + lc->lissajous = (lisas *) NULL; + } +} + +static Bool +drawlisa(ModeInfo * mi, lisas * loop) +{ + XPoint *np; + XPoint *lp = loop->lastpoint; + lisacons *lc = &Lisa[MI_SCREEN(mi)]; + lisafuncs **lf = loop->function; + int phase = lc->loopcount % loop->nsteps; + int pctr, fctr, xctr, yctr, extra_points; + double xprod, yprod, xsum, ysum; + + /* 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(mi); + return False; + } + + /* Update the center */ + loop->center.x += loop->dx; + loop->center.y += loop->dy; + 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); + } else if ((loop->center.x + loop->radius) >= lc->width) { + loop->center.x = lc->width - loop->radius; + loop->dx = -NRAND(XVMAX); + }; + if ((loop->center.y - loop->radius) <= 0) { + loop->center.y = loop->radius; + loop->dy = NRAND(YVMAX); + } else if ((loop->center.y + loop->radius) >= lc->height) { + loop->center.y = lc->height - loop->radius; + loop->dy = -NRAND(YVMAX); + }; + + /* Now draw the points, and erase the ones from the last cycle */ + + for (pctr = 0; pctr < loop->nsteps; pctr++) { + fctr = loop->nfuncs; + loop->phi = (double) (pctr - phase) * loop->pistep; + loop->theta = (double) (pctr + phase) * loop->pistep; + xsum = ysum = 0; + while (fctr--) { + xctr = lf[fctr]->nx; + yctr = lf[fctr]->ny; + if (additive) { + xprod = yprod = 0.0; + while (xctr--) + xprod += sin(lf[fctr]->xcoeff[xctr] * loop->theta); + while (yctr--) + yprod += sin(lf[fctr]->ycoeff[yctr] * loop->phi); + if (loop->melting) { + if (fctr) { + xsum += xprod * (double) (loop->nsteps - loop->melting) / + (double) loop->nsteps; + ysum += yprod * (double) (loop->nsteps - loop->melting) / + (double) loop->nsteps; + } else { + xsum += xprod * (double) loop->melting / (double) loop->nsteps; + ysum += yprod * (double) loop->melting / (double) loop->nsteps; + } + } else { + xsum = xprod; + ysum = yprod; + } + if (!fctr) { + xsum = xsum * (double) loop->radius / (double) lf[fctr]->nx; + ysum = ysum * (double) loop->radius / (double) lf[fctr]->ny; + } + } else { + if (loop->melting) { + if (fctr) { + yprod = xprod = (double) loop->radius * + (double) (loop->nsteps - loop->melting) / + (double) (loop->nsteps); + } else { + yprod = xprod = (double) loop->radius * + (double) (loop->melting) / (double) (loop->nsteps); + } + } else { + xprod = yprod = (double) loop->radius; + } + 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) && (!loop->melting)) { + xsum /= (double) loop->nfuncs; + ysum /= (double) loop->nfuncs; + } + xsum += (double) loop->center.x; + ysum += (double) loop->center.y; + + 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]; + } + } + + /* 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, + LINESTYLE, LINECAP, LINEJOIN); + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), &lp[pctr], + loop->cstep, CoordModeOrigin); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &np[pctr], loop->cstep, CoordModeOrigin); + XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, + LINESTYLE, LINECAP, LINEJOIN); +#else + /* erase the last cycle's point */ + XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi)); + XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), + &lp[pctr], loop->cstep, CoordModeOrigin); + + /* Set the new color */ + SET_COLOR(); + + /* plot this cycle's point */ + 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; +} + +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, 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(mi); + 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; + } + 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 = 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 */ + } + } 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 /* 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, + LINESTYLE, LINECAP, LINEJOIN); +#endif /* DRAWLINES */ + return True; +} + +static void +refreshlisa(ModeInfo * mi) +{ + lisacons *lc = &Lisa[MI_SCREEN(mi)]; + int lctr; + + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + if (!drawlisa(mi, &lc->lissajous[lctr])) + return; + } +} + +#ifndef STANDALONE +ENTRYPOINT void +refresh_lisa(ModeInfo * mi) +{ + lisacons *lc; + + if (Lisa == NULL) + return; + lc = &Lisa[MI_SCREEN(mi)]; + if (lc->lissajous == NULL) + return; + + if (lc->painted) { + lc->painted = False; + MI_CLEARWINDOW(mi); + refreshlisa(mi); + } +} +#endif + +static void +change_lisa(ModeInfo * mi) +{ + lisas *loop; + int lctr, newfunc; + lisacons *lc; + + if (Lisa == NULL) + return; + lc = &Lisa[MI_SCREEN(mi)]; + if (lc->lissajous == NULL) + return; + + lc->loopcount = 0; + 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 */ + } +} + +ENTRYPOINT void +init_lisa (ModeInfo * mi) +{ + int lctr; + lisacons *lc; + + MI_INIT (mi, Lisa); + lc = &Lisa[MI_SCREEN(mi)]; + lc->width = MI_WIDTH(mi); + lc->height = MI_HEIGHT(mi); + lc->loopcount = 0; + lc->nlissajous = MI_COUNT(mi); + if (lc->nlissajous <= 0) + lc->nlissajous = 1; + MI_CLEARWINDOW(mi); + lc->painted = False; + + if (lc->lissajous == NULL) { + if ((lc->lissajous = (lisas *) calloc(lc->nlissajous, + sizeof (lisas))) == NULL) + return; + for (lctr = 0; lctr < lc->nlissajous; lctr++) { + if (!initlisa(mi, &lc->lissajous[lctr])) + return; + lc->loopcount++; + } + } else { + refreshlisa(mi); + } +} + +ENTRYPOINT void +draw_lisa (ModeInfo * mi) +{ + lisacons *lc; + + if (Lisa == NULL) + return; + lc = &Lisa[MI_SCREEN(mi)]; + 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) { + change_lisa(mi); + } + refreshlisa(mi); +} + +XSCREENSAVER_MODULE ("Lisa", lisa) + +#endif /* MODE_lisa */ -- cgit v1.2.3-55-g7522