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/bubble.c | |
parent | 3928433848e2d6a9356f3d438a14b32a4f87f660 (diff) |
Importing xlockmore 5.22
Diffstat (limited to 'app/xlockmore/modes/bubble.c')
-rw-r--r-- | app/xlockmore/modes/bubble.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/app/xlockmore/modes/bubble.c b/app/xlockmore/modes/bubble.c new file mode 100644 index 000000000..4107cadf8 --- /dev/null +++ b/app/xlockmore/modes/bubble.c @@ -0,0 +1,312 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* bubble --- simple exploding bubbles */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)bubble.c 5.00 2000/11/01 xlockmore"; + +#endif + +/*- + * Copyright (c) 1998 by Charles Vidal <cvidal@ivsweb.com> + * http://www.chez.com/vidalc + * and David Bagley + * + * 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-Jan-1998: Written. + */ + +#ifdef STANDALONE +#define MODE_bubble +#define PROGCLASS "Bubble" +#define HACK_INIT init_bubble +#define HACK_DRAW draw_bubble +#define bubble_opts xlockmore_opts +#define DEFAULTS "*delay: 100000 \n" \ + "*count: 25 \n" \ + "*size: 100 \n" \ + "*ncolors: 200 \n" \ + "*fullrandom: True \n" +#define UNIFORM_COLORS +#include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +#include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + +#ifdef MODE_bubble + +#define DEF_BOIL "False" +static Bool boil; + +static XrmOptionDescRec opts[] = +{ + {(char *) "-boil", (char *) ".bubble.boil", XrmoptionNoArg, (caddr_t) "on"}, + {(char *) "+boil", (char *) ".bubble.boil", XrmoptionNoArg, (caddr_t) "off"} +}; +static argtype vars[] = +{ + {(void *) & boil, (char *) "boil", (char *) "Boil", (char *) DEF_BOIL, t_Bool} +}; +static OptionStruct desc[] = +{ + {(char *) "-/+boil", (char *) "turn on/off boil"} +}; + +ModeSpecOpt bubble_opts = +{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct bubble_description = +{"bubble", "init_bubble", "draw_bubble", "release_bubble", + "refresh_bubble", "init_bubble", (char *) NULL, &bubble_opts, + 100000, 25, 1, 100, 64, 0.6, "", + "Shows popping bubbles", 0, NULL}; + +#endif + +typedef struct { + int x, y, life; +} bubbletype; + +#define MINSIZE 20 +#define MINBUBBLES 1 + +typedef struct { + int direction; + int color; + int width, height; + int nbubbles; + Bool boil; + bubbletype *bubble; + int d; + Pixmap dbuf; + GC dbuf_gc; +} bubblestruct; + +static bubblestruct *bubbles = (bubblestruct *) NULL; + +static void +updateBubble(ModeInfo * mi, int i) +{ + bubblestruct *bp = &bubbles[MI_SCREEN(mi)]; + int x, diameter, x4, y4, diameter4; + + if (bp->bubble[i].life + 1 > bp->d - NRAND(16) || + bp->bubble[i].y < 0) { + bp->bubble[i].life = 0; + return; + } + ++bp->bubble[i].life; + diameter = bp->bubble[i].life; + x = bp->bubble[i].x; + if (bp->boil) { + bp->bubble[i].y -= diameter / 2; + x += (int) (cos((double) (diameter + + bp->bubble[i].x) / (M_PI / 5.0)) * (double) diameter); + } + /* SunOS 4.1.X xnews server may crash without this */ + if (diameter < 4) { + XFillRectangle(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc, + x - diameter / 2, bp->bubble[i].y - diameter / 2, + diameter, diameter); + } else { + XDrawArc(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc, + x - diameter / 2, bp->bubble[i].y - diameter / 2, + diameter, diameter, 0, 23040); + } + diameter4 = diameter / 4; + if (diameter4 > 0) { + x4 = x - diameter4 / 2 + + ((bp->direction / 2) ? (-1) : 1) * diameter / 6; + y4 = bp->bubble[i].y - diameter4 / 2 + + ((bp->direction % 2) ? 1 : (-1)) * diameter / 6; + /* SunOS 4.1.X xnews server may crash without this */ + if (diameter4 < 4) { + XFillRectangle(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc, + x4, y4, diameter4, diameter4); + } else { + XFillArc(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc, + x4, y4, diameter4, diameter4, 0, 23040); + } + } +} + +static void +changeBubble(ModeInfo * mi) +{ + bubblestruct *bp = &bubbles[MI_SCREEN(mi)]; + int i; + + for (i = 0; i < bp->nbubbles; i++) { + if (bp->bubble[i].life != 0) + updateBubble(mi, i); + } + i = NRAND(bp->nbubbles); + if (bp->bubble[i].life == 0) { + bp->bubble[i].x = NRAND(bp->width); + if (bp->boil) + bp->bubble[i].y = bp->height - + ((bp->height >= 16) ? NRAND(bp->height / 16) : 0); + else + bp->bubble[i].y = NRAND(bp->height); + updateBubble(mi, i); + } +} + +static void +free_bubble(Display *display, bubblestruct *bp) +{ + if (bp->dbuf != None) { + XFreePixmap(display, bp->dbuf); + bp->dbuf = None; + } + if (bp->dbuf_gc != None) { + XFreeGC(display, bp->dbuf_gc); + bp->dbuf_gc = None; + } + if (bp->bubble != NULL) { + free(bp->bubble); + bp->bubble = (bubbletype *) NULL; + } +} + +void +init_bubble(ModeInfo * mi) +{ + bubblestruct *bp; + int size = MI_SIZE(mi); + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + XGCValues gcv; + + if (bubbles == NULL) { + if ((bubbles = (bubblestruct *) calloc(MI_NUM_SCREENS(mi), + sizeof (bubblestruct))) == NULL) + return; + } + bp = &bubbles[MI_SCREEN(mi)]; + + bp->width = MI_WIDTH(mi); + bp->height = MI_HEIGHT(mi); + bp->direction = NRAND(4); + if (MI_IS_FULLRANDOM(mi)) + bp->boil = (Bool) (LRAND() & 1); + else + bp->boil = boil; + + if (size < -MINSIZE) + bp->d = NRAND(MIN(-size, MAX(MINSIZE, + MIN(bp->width, bp->height) / 2)) - MINSIZE + 1) + MINSIZE; + else if (size < MINSIZE) { + if (!size) + bp->d = MAX(MINSIZE, MIN(bp->width, bp->height) / 2); + else + bp->d = MINSIZE; + } else + bp->d = MIN(size, MAX(MINSIZE, + MIN(bp->width, bp->height) / 2)); + bp->nbubbles = MI_COUNT(mi); + if (bp->nbubbles < -MINBUBBLES) { + bp->nbubbles = NRAND(-bp->nbubbles - MINBUBBLES + 1) + MINBUBBLES; + } else if (bp->nbubbles < MINBUBBLES) + bp->nbubbles = MINBUBBLES; + if (bp->bubble != NULL) + free(bp->bubble); + if ((bp->bubble = (bubbletype *) calloc(bp->nbubbles, + sizeof (bubbletype))) == NULL) { + free_bubble(display, bp); + return; + } + if (MI_NPIXELS(mi) > 2) + bp->color = NRAND(MI_NPIXELS(mi)); + + if (bp->dbuf != None) + XFreePixmap(display, bp->dbuf); + if ((bp->dbuf = XCreatePixmap(display, window, bp->width, bp->height, + 1)) == None) { + free_bubble(display, bp); + return; + } + /* Do not want any exposure events from XCopyPlane */ + XSetGraphicsExposures(display, MI_GC(mi), False); + + gcv.foreground = 1; + gcv.background = 0; + gcv.function = GXcopy; + gcv.graphics_exposures = False; + gcv.line_width = 2; + if (bp->dbuf_gc) + XFreeGC(display, bp->dbuf_gc); + if ((bp->dbuf_gc = XCreateGC(display, bp->dbuf, + GCForeground | GCBackground | GCLineWidth | GCFunction, + &gcv)) == None) { + free_bubble(display, bp); + return; + } + MI_CLEARWINDOW(mi); +} + +void +draw_bubble(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + bubblestruct *bp; + + if (bubbles == NULL) + return; + bp = &bubbles[MI_SCREEN(mi)]; + if (bp->bubble == NULL) + return; + + MI_IS_DRAWN(mi) = True; + if (MI_NPIXELS(mi) <= 2) + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + else { + bp->color = (bp->color + 1) % MI_NPIXELS(mi); + XSetForeground(display, gc, MI_PIXEL(mi, bp->color)); + } + if (bp->dbuf) { + XSetForeground(display, bp->dbuf_gc, 0); + XFillRectangle(display, bp->dbuf, bp->dbuf_gc, + 0, 0, bp->width, bp->height); + XSetForeground(display, bp->dbuf_gc, 1); + changeBubble(mi); + XCopyPlane(display, bp->dbuf, window, gc, + 0, 0, bp->width, bp->height, 0, 0, 1); + } +} + +void +release_bubble(ModeInfo * mi) +{ + if (bubbles != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) + free_bubble(MI_DISPLAY(mi), &bubbles[screen]); + free(bubbles); + bubbles = (bubblestruct *) NULL; + } +} + +void +refresh_bubble(ModeInfo * mi) +{ + /* Do nothing, it will refresh by itself */ +} + +#endif /* MODE_bubble */ |