diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 11:09:41 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 11:09:41 +0000 |
commit | 95c2d1cbda23a41cdf6e63520c7f0b825e63dd5b (patch) | |
tree | 06d3ffa4312e568c4157f69fe1bddaddec9bc497 /app/xlockmore/modes/worm.c | |
parent | 3928433848e2d6a9356f3d438a14b32a4f87f660 (diff) |
Importing xlockmore 5.22
Diffstat (limited to 'app/xlockmore/modes/worm.c')
-rw-r--r-- | app/xlockmore/modes/worm.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/app/xlockmore/modes/worm.c b/app/xlockmore/modes/worm.c new file mode 100644 index 000000000..699988a17 --- /dev/null +++ b/app/xlockmore/modes/worm.c @@ -0,0 +1,475 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* worm --- draw wiggly worms */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)worm.c 5.00 2000/11/01 xlockmore"; + +#endif + +/*- + * Copyright (c) 1991 by Patrick J. Naughton. + * + * 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: + * 01-Nov-2000: Allocation checks + * 10-May-1997: Compatible with xscreensaver + * 03-Sep-1996: fixed bug in allocation of space for worms, added 3d support + * Henrik Theiling <theiling@coli.uni-sb.de> + * 27-Sep-1995: put back malloc + * 23-Sep-1993: got rid of "rint". (David Bagley) + * 27-Sep-1991: got rid of all malloc calls since there were no calls to free(). + * 25-Sep-1991: Integrated into X11R5 contrib xlock. + * + * Adapted from a concept in the Dec 87 issue of Scientific American p. 142. + * + * SunView version: Brad Taylor <brad@sun.com> + * X11 version: Dave Lemke <lemke@ncd.com> + * xlock version: Boris Putanec <bp@cs.brown.edu> + */ + +#ifdef STANDALONE +#define MODE_worm +#define PROGCLASS "Worm" +#define HACK_INIT init_worm +#define HACK_DRAW draw_worm +#define worm_opts xlockmore_opts +#define DEFAULTS "*delay: 17000 \n" \ + "*count: -20 \n" \ + "*cycles: 10 \n" \ + "*size: -3 \n" \ + "*ncolors: 200 \n" \ + "*use3d: False \n" \ + "*delta3d: 1.5 \n" \ + "*right3d: red \n" \ + "*left3d: blue \n" \ + "*both3d: magenta \n" \ + "*none3d: black \n" +#define SMOOTH_COLORS +#include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +#include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_worm + +ModeSpecOpt worm_opts = +{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +#ifdef USE_MODULES +ModStruct worm_description = +{"worm", "init_worm", "draw_worm", "release_worm", + "refresh_worm", "init_worm", (char *) NULL, &worm_opts, + 17000, -20, 10, -3, 64, 1.0, "", + "Shows wiggly worms", 0, NULL}; + +#endif + +#define MINSIZE 1 + +#define SEGMENTS 36 +#define MINWORMS 1 + +#define MAXZ 750 +#define MINZ 100 +#define SCREENZ 200 +#define GETZDIFF(z) (MI_DELTA3D(mi)*20.0*(1.0-(SCREENZ)/((float)(z)+MINZ))) +#define IRINT(x) ((int)(((x)>0.0)?(x)+0.5:(x)-0.5)) + +/* How many segments to draw per cycle when redrawing */ +#define REDRAWSTEP 3 + +typedef struct { + XPoint *circ; + int *diffcirc; + int dir, dir2; + int tail; + int x, y, z; + int redrawing, redrawpos; +} wormstuff; + +typedef struct { + int xsize, ysize, zsize; + int wormlength; + int nc; + int nw; + int circsize; + wormstuff *worm; + XRectangle *rects; + int maxsize; + int *size; + unsigned int chromo; +} wormstruct; + +static float sintab[SEGMENTS]; +static float costab[SEGMENTS]; +static int init_table = 0; + +static wormstruct *worms = (wormstruct *) NULL; + +static void +worm_doit(ModeInfo * mi, int which, unsigned long color) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + wormstruct *wp = &worms[MI_SCREEN(mi)]; + wormstuff *ws = &wp->worm[which]; + int x, y, z; + int diff; + + ws->tail++; + if (ws->tail == wp->wormlength) + ws->tail = 0; + + x = ws->circ[ws->tail].x; + y = ws->circ[ws->tail].y; + + if (MI_IS_USE3D(mi)) { + diff = ws->diffcirc[ws->tail]; + if (MI_IS_INSTALL(mi)) { + XSetForeground(display, gc, MI_NONE_COLOR(mi)); + } else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + } + XFillRectangle(display, window, gc, x - diff, y, + wp->circsize, wp->circsize); + XFillRectangle(display, window, gc, x + diff, y, + wp->circsize, wp->circsize); + } else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XFillRectangle(display, window, gc, x, y, wp->circsize, wp->circsize); + } + + if (LRAND() & 1) + ws->dir = (ws->dir + 1) % SEGMENTS; + else + ws->dir = (ws->dir + SEGMENTS - 1) % SEGMENTS; + + x = (ws->x + IRINT((float) wp->circsize * costab[ws->dir]) + + wp->xsize) % wp->xsize; + y = (ws->y + IRINT((float) wp->circsize * sintab[ws->dir]) + + wp->ysize) % wp->ysize; + + ws->circ[ws->tail].x = x; + ws->circ[ws->tail].y = y; + ws->x = x; + ws->y = y; + + if (MI_IS_USE3D(mi)) { + if (LRAND() & 1) + ws->dir2 = (ws->dir2 + 1) % SEGMENTS; + else + ws->dir2 = (ws->dir2 + SEGMENTS - 1) % SEGMENTS; + /* for the z-axis the wrap-around looks bad, + * so worms should just turn around. + */ + z = (int) (ws->z + wp->circsize * sintab[ws->dir2]); + if (z < 0 || z >= wp->zsize) + z = (int) (ws->z - wp->circsize * sintab[ws->dir2]); + + diff = (int) (GETZDIFF(z) + 0.5); /* ROUND */ + ws->diffcirc[ws->tail] = diff; + + ws->z = z; + + /* right eye */ + color = 0; + wp->rects[color * wp->maxsize + wp->size[color]].x = x + diff; + wp->rects[color * wp->maxsize + wp->size[color]].y = y; + wp->size[color]++; + + /* left eye */ + color = 1; + wp->rects[color * wp->maxsize + wp->size[color]].x = x - diff; + wp->rects[color * wp->maxsize + wp->size[color]].y = y; + wp->size[color]++; + +#if 0 + if (ws->redrawing) { /* Too hard for now */ + int j; + + for (j = 0; j < REDRAWSTEP; j++) { + int k = (ws->tail - ws->redrawpos + wp->wormlength) + % wp->wormlength; + + color = 0; + wp->rects[color * wp->maxsize + wp->size[color]].x = + ws->circ[k].x + ws->diffcirc[k]; + wp->rects[color * wp->maxsize + wp->size[color]].y = + ws->circ[k].y; + wp->size[color]++; + + color = 1; + wp->rects[color * wp->maxsize + wp->size[color]].x = + ws->circ[k].x - ws->diffcirc[k]; + wp->rects[color * wp->maxsize + wp->size[color]].y = + ws->circ[k].y; + wp->size[color]++; + + if (++(ws->redrawpos) >= wp->wormlength) { + ws->redrawing = 0; + break; + } + } + } +#endif + + } else { + + wp->rects[color * wp->maxsize + wp->size[color]].x = x; + wp->rects[color * wp->maxsize + wp->size[color]].y = y; + wp->size[color]++; + if (ws->redrawing) { + int j; + + ws->redrawpos++; + /* Compensates for the changed ws->tail + since the last callback. */ + + for (j = 0; j < REDRAWSTEP; j++) { + int k = (ws->tail - ws->redrawpos + wp->wormlength) + % wp->wormlength; + + wp->rects[color * wp->maxsize + wp->size[color]].x = ws->circ[k].x; + wp->rects[color * wp->maxsize + wp->size[color]].y = ws->circ[k].y; + wp->size[color]++; + + if (++(ws->redrawpos) >= wp->wormlength) { + ws->redrawing = 0; + break; + } + } + } + } +} + +static void +free_worm(wormstruct * wp) +{ + int wn; + + if (wp->worm) { + for (wn = 0; wn < wp->nw; wn++) { + if (wp->worm[wn].circ) + free(wp->worm[wn].circ); + if (wp->worm[wn].diffcirc) + free(wp->worm[wn].diffcirc); + } + free(wp->worm); + wp->worm = (wormstuff *) NULL; + } + if (wp->rects) { + free(wp->rects); + wp->rects = (XRectangle *) NULL; + } + if (wp->size) { + free(wp->size); + wp->size = (int *) NULL; + } +} + +void +init_worm(ModeInfo * mi) +{ + wormstruct *wp; + int size = MI_SIZE(mi); + int i, j; + + if (worms == NULL) { + if ((worms = (wormstruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (wormstruct))) == NULL) + return; + } + wp = &worms[MI_SCREEN(mi)]; + if (MI_NPIXELS(mi) <= 2 || MI_IS_USE3D(mi)) + wp->nc = 2; + else + wp->nc = MI_NPIXELS(mi); + + free_worm(wp); + wp->nw = MI_COUNT(mi); + if (wp->nw < -MINWORMS) + wp->nw = NRAND(-wp->nw - MINWORMS + 1) + MINWORMS; + else if (wp->nw < MINWORMS) + wp->nw = MINWORMS; + if (!wp->worm) + if ((wp->worm = (wormstuff *) malloc(wp->nw * + sizeof (wormstuff))) == NULL) { + free_worm(wp); + return; + } + + if (!wp->size) + if ((wp->size = (int *) malloc(MI_NPIXELS(mi) * + sizeof (int))) == NULL) { + free_worm(wp); + return; + } + + wp->maxsize = (REDRAWSTEP + 1) * wp->nw; /* / wp->nc + 1; */ + if (!wp->rects) + if ((wp->rects = (XRectangle *) malloc(wp->maxsize * MI_NPIXELS(mi) * + sizeof (XRectangle))) == NULL) { + free_worm(wp); + return; + } + + if (!init_table) { + init_table = 1; + for (i = 0; i < SEGMENTS; i++) { + sintab[i] = SINF(i * 2.0 * M_PI / SEGMENTS); + costab[i] = COSF(i * 2.0 * M_PI / SEGMENTS); + } + } + wp->xsize = MI_WIDTH(mi); + wp->ysize = MI_HEIGHT(mi); + wp->zsize = MAXZ - MINZ + 1; + if (MI_NPIXELS(mi) > 2) + wp->chromo = NRAND(MI_NPIXELS(mi)); + + if (size < -MINSIZE) + wp->circsize = NRAND(-size - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) + wp->circsize = MINSIZE; + else + wp->circsize = size; + + for (i = 0; i < wp->nc; i++) { + for (j = 0; j < wp->maxsize; j++) { + wp->rects[i * wp->maxsize + j].width = wp->circsize; + wp->rects[i * wp->maxsize + j].height = wp->circsize; + + } + } + (void) memset((char *) wp->size, 0, wp->nc * sizeof (int)); + + wp->wormlength = (int) sqrt((double) wp->xsize + wp->ysize) * + MI_CYCLES(mi) / 8; /* Fudge this to something reasonable */ + if (wp->wormlength < 1) + wp->wormlength = 1; + for (i = 0; i < wp->nw; i++) { + if (((wp->worm[i].circ = (XPoint *) malloc(wp->wormlength * + sizeof (XPoint))) == NULL) || + ((wp->worm[i].diffcirc = (int *) malloc(wp->wormlength * + sizeof (int))) == NULL)) { + free_worm(wp); + return; + } + + for (j = 0; j < wp->wormlength; j++) { + wp->worm[i].circ[j].x = wp->xsize / 2; + wp->worm[i].circ[j].y = wp->ysize / 2; + if (MI_IS_USE3D(mi)) + wp->worm[i].diffcirc[j] = 0; + } + wp->worm[i].dir = NRAND(SEGMENTS); + wp->worm[i].dir2 = NRAND(SEGMENTS); + wp->worm[i].tail = 0; + wp->worm[i].x = wp->xsize / 2; + wp->worm[i].y = wp->ysize / 2; + wp->worm[i].z = SCREENZ - MINZ; + wp->worm[i].redrawing = 0; + } + + if (MI_IS_INSTALL(mi) && MI_IS_USE3D(mi)) { + MI_CLEARWINDOWCOLOR(mi, MI_NONE_COLOR(mi)); + } else { + MI_CLEARWINDOW(mi); + } +} + +void +draw_worm(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + wormstruct *wp = &worms[MI_SCREEN(mi)]; + unsigned long wcolor; + int i; + + (void) memset((char *) wp->size, 0, wp->nc * sizeof (int)); + + MI_IS_DRAWN(mi) = True; + + for (i = 0; i < wp->nw; i++) { + if (MI_NPIXELS(mi) > 2) { + wcolor = (i + wp->chromo) % wp->nc; + + worm_doit(mi, i, wcolor); + } else + worm_doit(mi, i, (unsigned long) 0); + } + + if (MI_IS_USE3D(mi)) { + if (MI_IS_INSTALL(mi)) + XSetFunction(display, gc, GXor); + XSetForeground(display, gc, MI_RIGHT_COLOR(mi)); + XFillRectangles(display, window, gc, &(wp->rects[0]), wp->size[0]); + + XSetForeground(display, gc, MI_LEFT_COLOR(mi)); + XFillRectangles(display, window, gc, &(wp->rects[wp->maxsize]), wp->size[1]); + if (MI_IS_INSTALL(mi)) + XSetFunction(display, gc, GXcopy); + } else if (MI_NPIXELS(mi) > 2) { + for (i = 0; i < wp->nc; i++) { + XSetForeground(display, gc, MI_PIXEL(mi, i)); + XFillRectangles(display, window, gc, &(wp->rects[i * wp->maxsize]), wp->size[i]); + } + } else { + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + XFillRectangles(display, window, gc, + &(wp->rects[0]), wp->size[0]); + } + + if (++wp->chromo == (unsigned long) wp->nc) + wp->chromo = 0; +} + +void +release_worm(ModeInfo * mi) +{ + if (worms != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_worm(&worms[screen]); + free(worms); + worms = (wormstruct *) NULL; + } +} + +void +refresh_worm(ModeInfo * mi) +{ + if (MI_IS_INSTALL(mi) && MI_IS_USE3D(mi)) { + MI_CLEARWINDOWCOLOR(mi, MI_NONE_COLOR(mi)); + } else { + MI_CLEARWINDOW(mi); + } + /* The 3D code does drawing&clearing by XORing. We do not + want to go to too much trouble here to make it redraw + correctly. */ + if (!MI_IS_USE3D(mi) && worms != NULL) { + wormstruct *wp = &worms[MI_SCREEN(mi)]; + int i; + + for (i = 0; i < wp->nw; i++) { + wp->worm[i].redrawing = 1; + wp->worm[i].redrawpos = 0; + } + } +} + +#endif /* MODE_worm */ |