summaryrefslogtreecommitdiff
path: root/app/xlockmore/modes/worm.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 11:09:41 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 11:09:41 +0000
commit95c2d1cbda23a41cdf6e63520c7f0b825e63dd5b (patch)
tree06d3ffa4312e568c4157f69fe1bddaddec9bc497 /app/xlockmore/modes/worm.c
parent3928433848e2d6a9356f3d438a14b32a4f87f660 (diff)
Importing xlockmore 5.22
Diffstat (limited to 'app/xlockmore/modes/worm.c')
-rw-r--r--app/xlockmore/modes/worm.c475
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 */