xenocara/app/xlockmore/modes/deco.c
2006-11-26 11:07:42 +00:00

193 lines
5.2 KiB
C

/* -*- Mode: C; tab-width: 4 -*- */
/* deco --- art as ugly as sin */
#if !defined( lint ) && !defined( SABER )
static const char sccsid[] = "@(#)deco.c 5.00 2000/11/01 xlockmore";
#endif
/*
* Copyright (c) 1997 by Jamie Zawinski <jwz@jwz.org>
*
* 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
* 29-Oct-1997: xlock version (David Bagley <bagleyd@tux.org>)
* 1997: xscreensaver version Jamie Zawinski <jwz@jwz.org>
*/
/*-
* original copyright
* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* Concept snarfed from Michael D. Bayne in
* http://www.go2net.com/internet/deep/1997/04/16/body.html
*/
#ifdef STANDALONE
#define MODE_deco
#define PROGCLASS "Deco"
#define HACK_INIT init_deco
#define HACK_DRAW draw_deco
#define deco_opts xlockmore_opts
#define DEFAULTS "*delay: 1000000 \n" \
"*count: -30 \n" \
"*cycles: 2 \n" \
"*size: -10 \n" \
"*ncolors: 200 \n"
#include "xlockmore.h" /* in xscreensaver distribution */
#else /* STANDALONE */
#include "xlock.h" /* in xlockmore distribution */
#endif /* STANDALONE */
#ifdef MODE_deco
ModeSpecOpt deco_opts =
{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
#ifdef USE_MODULES
ModStruct deco_description =
{"deco", "init_deco", "draw_deco", "release_deco",
"init_deco", "init_deco", (char *) NULL, &deco_opts,
1000000, -30, 2, -10, 64, 0.6, "",
"Shows art as ugly as sin", 0, NULL};
#endif
#define MINSIZE 2
#define MINDEPTH 1
typedef struct {
int max_depth;
int min_height;
int min_width;
int time;
int colorindex;
unsigned long bordercolor;
} decostruct;
static decostruct *decos = (decostruct *) NULL;
static void
deco(ModeInfo * mi, int x, int y, int w, int h, int depth)
{
Display *display = MI_DISPLAY(mi);
Window window = MI_WINDOW(mi);
GC gc = MI_GC(mi);
decostruct *dp = &decos[MI_SCREEN(mi)];
if ((NRAND(dp->max_depth) + 1 < depth) ||
(w < dp->min_width) || (h < dp->min_height)) {
if (w > 2 && h > 2) {
if (MI_NPIXELS(mi) > 2) {
XSetForeground(display, gc, MI_PIXEL(mi, dp->colorindex));
if (++dp->colorindex >= MI_NPIXELS(mi))
dp->colorindex = 0;
} else
XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
XFillRectangle(display, window, gc, x + 1, y + 1, w - 2, h - 2);
}
} else {
if (LRAND() & 1) {
deco(mi, x, y, w / 2, h, depth + 1);
deco(mi, x + w / 2, y, w - w / 2, h, depth + 1);
} else {
deco(mi, x, y, w, h / 2, depth + 1);
deco(mi, x, y + h / 2, w, h - h / 2, depth + 1);
}
}
}
void
init_deco(ModeInfo * mi)
{
decostruct *dp;
int depth = MI_COUNT(mi);
int size = MI_SIZE(mi);
if (decos == NULL) {
if ((decos = (decostruct *) calloc(MI_NUM_SCREENS(mi),
sizeof (decostruct))) == NULL)
return;
}
dp = &decos[MI_SCREEN(mi)];
if (MI_NPIXELS(mi) > 2) {
dp->bordercolor = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
dp->colorindex = NRAND(MI_NPIXELS(mi));
} else
dp->bordercolor = MI_BLACK_PIXEL(mi);
if (depth < -MINDEPTH)
dp->max_depth = NRAND(-depth - MINDEPTH + 1) + MINDEPTH;
else if (depth < MINDEPTH)
dp->max_depth = MINDEPTH;
else
dp->max_depth = depth;
if (size < -MINSIZE) {
dp->min_width = NRAND(-size - MINSIZE + 1) + MINSIZE;
dp->min_height = NRAND(-size - MINSIZE + 1) + MINSIZE;
} else if (size < MINDEPTH)
dp->min_width = dp->min_height = MINSIZE;
else
dp->min_width = dp->min_height = size;
dp->time = 0;
}
void
draw_deco(ModeInfo * mi)
{
decostruct *dp;
if (decos == NULL)
return;
dp = &decos[MI_SCREEN(mi)];
if (dp->time == 0) {
/* This fills up holes */
MI_CLEARWINDOWCOLOR(mi, dp->bordercolor);
#ifdef SOLARIS2
/*
* if this is not done the first rectangle is sometimes messed up on
* Solaris2 with 24 bit TrueColor (Ultra2)
*/
XDrawRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
0, 0, MI_WIDTH(mi) / 2 + 1, MI_HEIGHT(mi) / 2 + 1);
#endif
deco(mi, 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi), 0);
}
if (++dp->time > MI_CYCLES(mi))
init_deco(mi);
MI_IS_DRAWN(mi) = True;
}
void
release_deco(ModeInfo * mi)
{
if (decos != NULL) {
free(decos);
decos = (decostruct *) NULL;
}
}
#endif /* MODE_deco */