+++ /dev/null
-/* -*- Mode: C; tab-width: 4 -*- */
-/* lisa --- animated full-loop lisajous figures */
-
-#if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)lisa.c 4.04 97/07/28 xlockmore";
-#endif
-
-/* Copyright (c) 1997 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:
- * 10-May-97: 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
- * 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.
- */
-
-#ifdef STANDALONE
-# 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" /* from the xscreensaver distribution */
- void refresh_lisa(ModeInfo * mi);
- void change_lisa(ModeInfo * mi);
-#else /* !STANDALONE */
-# include "xlock.h" /* from the xlockmore distribution */
-#endif /* !STANDALONE */
-
-#define DEF_ADDITIVE "True"
-
-static Bool additive;
-
-static XrmOptionDescRec lisa_xrm_opts[] =
-{
- {"-additive", ".lisa.additive", XrmoptionNoArg, (caddr_t) "True"},
- {"+additive", ".lisa.additive", XrmoptionNoArg, (caddr_t) "False"}
-};
-
-static argtype lisa_vars[] =
-{
- {(caddr_t *) & additive, "additive", "Additive", DEF_ADDITIVE, t_Bool}
-};
-
-static OptionStruct lisa_vars_desc[] =
-{
- {"-/+additive", "turn on/off additive functions mode"}
-};
-
-ModeSpecOpt lisa_opts =
-{2, lisa_xrm_opts, 1, lisa_vars, lisa_vars_desc};
-
-
-#define DRAWLINES 1
-#define TWOLOOPS 1
-#define XVMAX 10 /* Maximum velocities */
-#define YVMAX 10
-#define LISAMAXFUNCS 2
-#define NUMSTDFUNCS 10
-#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) >= MI_NPIXELS(mi)) { loop->color=0; } \
- } else { XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_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)
-
-
-typedef struct lisafunc_struct {
- double xcoeff[2], ycoeff[2];
- int nx, ny;
- int index;
-} lisafuncs;
-
-typedef struct lisa_struct {
- int radius, color, dx, dy, nsteps, nfuncs, melting;
- double pistep, phi, theta;
- XPoint center, *lastpoint;
- lisafuncs *function[LISAMAXFUNCS];
-} lisas;
-
-typedef struct lisacontext_struct {
- lisas *lisajous;
- int width, height, nlisajous, loopcount;
- int maxcycles;
-} lisacons;
-
-static lisacons *Lisa = 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, 0.0},
- {1.0, 0.0}, 1, 1, 9}
-};
-
-static void
-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;
- double xprod, yprod, xsum, ysum;
-
- /* Allocate the np array */
- np = (XPoint *) calloc(loop->nsteps, sizeof (XPoint));
-
- /* Update the center */
- loop->center.x += loop->dx;
- loop->center.y += loop->dy;
- checkRadius(loop, lc);
- 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);
- }
- if (loop->melting) {
- if (!--loop->melting) {
- loop->nfuncs = 1;
- loop->function[0] = loop->function[1];
- }
- }
- for (pctr = 0; pctr < loop->nsteps; pctr++) {
-
-#if defined DRAWLINES
- /* erase the last cycle's point */
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_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 */
- lisasetcolor();
-
- /* 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);
-#else
- /* erase the last cycle's point */
- XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
- XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), \
- MI_GC(mi), lp[pctr].x, lp[pctr].y);
-
- /* Set the new color */
- lisasetcolor();
-
- /* plot this cycle's point */
- XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), \
- MI_GC(mi), np[pctr].x, np[pctr].y);
-#endif
- }
- (void) free((void *) lp);
- loop->lastpoint = np;
-}
-
-static void
-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_WIN_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 = 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)
- return;
- 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);
- }
- for (pctr = 0; pctr < loop->nsteps; pctr++) {
- /* Set the color */
- lisasetcolor();
-#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
- }
-
- {
- int line_width = -15; /* #### make this a resource */
- if (line_width == 0)
- line_width = -8;
- if (line_width < 0)
- line_width = NRAND(-line_width)+1;
- XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), line_width,
- LineSolid, CapProjecting, JoinMiter);
- }
-}
-
-void
-init_lisa(ModeInfo * mi)
-{
- lisacons *lc;
- int lctr;
-
- if (Lisa == NULL) {
- if ((Lisa = (lisacons *) calloc(MI_NUM_SCREENS(mi), sizeof (lisacons))) \
- == NULL)
- return;
- }
- lc = &Lisa[MI_SCREEN(mi)];
- lc->width = MI_WIN_WIDTH(mi);
- lc->height = MI_WIN_HEIGHT(mi);
- lc->loopcount = 0;
- lc->nlisajous = MI_BATCHCOUNT(mi);
- if (lc->nlisajous <= 0)
- lc->nlisajous = 1;
-
- if (lc->lisajous == NULL) {
- if ((lc->lisajous = (lisas *) calloc(lc->nlisajous, sizeof (lisas))) \
- == NULL)
- return;
- XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
- for (lctr = 0; lctr < lc->nlisajous; lctr++) {
- initlisa(mi, &lc->lisajous[lctr]);
- lc->loopcount++;
- }
- } else {
- refresh_lisa(mi);
- }
- XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
-}
-
-void
-draw_lisa(ModeInfo * mi)
-{
- lisacons *lc = &Lisa[MI_SCREEN(mi)];
-
- if (++lc->loopcount > lc->maxcycles) {
- change_lisa(mi);
- }
- refresh_lisa(mi);
-}
-
-void
-refresh_lisa(ModeInfo * mi)
-{
- lisacons *lc = &Lisa[MI_SCREEN(mi)];
- int lctr;
-
- for (lctr = 0; lctr < lc->nlisajous; lctr++) {
- drawlisa(mi, &lc->lisajous[lctr]);
- }
-}
-
-void
-release_lisa(ModeInfo * mi)
-{
- lisacons *lc;
- int lctr, sctr;
-
- if (Lisa) {
- for (sctr = 0; sctr < MI_NUM_SCREENS(mi); sctr++) {
- lc = &Lisa[sctr];
- while (lc->lisajous) {
- for (lctr = 0; lctr < lc->nlisajous; lctr++) {
- (void) free(lc->lisajous[lctr].lastpoint);
- }
- (void) free(lc->lisajous);
- lc->lisajous = NULL;
- }
- }
- (void) free(Lisa);
- Lisa = NULL;
- }
-}
-
-void
-change_lisa(ModeInfo * mi)
-{
- lisacons *lc = &Lisa[MI_SCREEN(mi)];
- lisas *loop;
- int lctr;
-
- 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;
- }
-}