/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997 * Jamie Zawinski * * 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. */ /* decayscreen * * Based on slidescreen program from the xscreensaver application and the * decay program for Sun framebuffers. This is the comment from the decay.c * file: * decay.c * find the screen bitmap for the console and make it "decay" by * randomly shifting random rectangles by one pixelwidth at a time. * * by David Wald, 1988 * rewritten by Natuerlich! * based on a similar "utility" on the Apollo ring at Yale. * X version by * * Vivek Khera * 5-AUG-1993 * * Hacked by jwz, 28-Nov-97 (sped up and added new motion directions) * R. Schultz * Added "melt" & "stretch" modes 28-Mar-1999 * */ /* * ported to Plan 9 by andrey@lanl.gov, 08/02 */ /* plan9-related stuff */ #include #include #include #include /* screenshot-related stuff */ #include "getscr.h" static uchar *scrbuf; static Image *scrimg; /* other defines */ #define NULL nil #define XPoint Point #define NRAND nrand #define LRAND lrand #define random rand #define MAXRAND ((2<<31)-1) #define MAX(a, b) (((a) > (b))?(a):(b)) #define MIN(a, b) (((a) < (b))?(a):(b)) #define RAND_MAX MAXRAND #define ABS abs Image *colors[256]; #define M_PI PI #define Bool int #define True 1 #define False 0 char *buttons[] = { "exit", 0 }; Menu menu = { buttons }; Mouse m; /* end of plan9-related defines */ static int sizex, sizey; static int delay = 1000; static int mode; static int iterations=1; #define SHUFFLE 0 #define UP 1 #define LEFT 2 #define RIGHT 3 #define DOWN 4 #define UPLEFT 5 #define DOWNLEFT 6 #define UPRIGHT 7 #define DOWNRIGHT 8 #define IN 9 #define OUT 10 #define MELT 11 #define STRETCH 12 #define FUZZ 13 static void init_decay (void) { mode = random() % (FUZZ+1); delay = 10; sizex = Dx(screen->r); sizey = Dy(screen->r); if (mode == MELT || mode == STRETCH) { /* make sure screen eventually turns background color */ line(screen, addpt(screen->r.min, Pt(0, 0)), addpt(screen->r.min, Pt(sizex, 1)), Endsquare, Endsquare, 0, display->black, ZP); /* slow down for smoother melting*/ iterations = 1; } } /* * perform one iteration of decay */ static void decay1 (void) { int left, top, width, height, toleft, totop; Rectangle r; Point p, p2; #define L 101 #define R 102 #define U 103 #define D 104 static int no_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D }; static int up_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D }; static int down_bias[] = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D }; static int left_bias[] = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D }; static int right_bias[] = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D }; static int upleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D }; static int downleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D }; static int upright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D }; static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D }; static int *bias; switch (mode) { case SHUFFLE: bias = no_bias; break; case UP: bias = up_bias; break; case LEFT: bias = left_bias; break; case RIGHT: bias = right_bias; break; case DOWN: bias = down_bias; break; case UPLEFT: bias = upleft_bias; break; case DOWNLEFT: bias = downleft_bias; break; case UPRIGHT: bias = upright_bias; break; case DOWNRIGHT: bias = downright_bias; break; case IN: bias = no_bias; break; case OUT: bias = no_bias; break; case MELT: bias = no_bias; break; case STRETCH: bias = no_bias; break; case FUZZ: bias = no_bias; break; default: abort(); } #define nrnd(x) (random() % (x)) if (mode == MELT || mode == STRETCH) { left = nrnd(sizex/2); top = nrnd(sizey); width = nrnd( sizex/2 ) + sizex/2 - left; height = nrnd(sizey - top); toleft = left; totop = top+1; } else if (mode == FUZZ) { /* By Vince Levey ; inspired by the "melt" mode of the "scrhack" IrisGL program by Paul Haeberli circa 1991. */ static int toggle = 0; left = nrnd(sizex - 1); top = nrnd(sizey - 1); toggle = !toggle; if (toggle) { totop = top; height = 1; toleft = nrnd(sizex - 1); if (toleft > left) { width = toleft-left; toleft = left; left++; } else { width = left-toleft; left = toleft; toleft++; } } else { toleft = left; width = 1; totop = nrnd(sizey - 1); if (totop > top) { height = totop-top; totop = top; top++; } else { height = top-totop; top = totop; totop++; } } } else { left = nrnd(sizex - 1); top = nrnd(sizey); width = nrnd(sizex - left); height = nrnd(sizey - top); toleft = left; totop = top; if (mode == IN || mode == OUT) { int x = left+(width/2); int y = top+(height/2); int cx = sizex/2; int cy = sizey/2; if (mode == IN) { if (x > cx && y > cy) bias = upleft_bias; else if (x < cx && y > cy) bias = upright_bias; else if (x < cx && y < cy) bias = downright_bias; else /* (x > cx && y < cy)*/ bias = downleft_bias; } else { if (x > cx && y > cy) bias = downright_bias; else if (x < cx && y > cy) bias = downleft_bias; else if (x < cx && y < cy) bias = upleft_bias; else /* (x > cx && y < cy)*/ bias = upright_bias; } } switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) { case L: toleft = left-1; break; case R: toleft = left+1; break; case U: totop = top-1; break; case D: totop = top+1; break; default: abort(); break; } } r = screen->r; if (mode == STRETCH) { p = addpt(r.min, Pt(0, sizey-top-1)); p2 = addpt(r.min, Pt(0, sizey-top-2)); r = Rpt(p, addpt(Pt(sizex, top+1), p)); // XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1, // 0, sizey-top-1); } else { p = addpt(r.min, Pt(toleft, totop)); p2 = addpt(r.min, Pt(left, top)); r = Rpt(p, addpt(Pt(width, height), p)); // XCopyArea (dpy, window, window, gc, left, top, width, height, // toleft, totop); } draw(screen, r, screen, nil, p2); #undef nrnd } void screenhack (void) { init_decay (); while (1) { int i; for (i = 0; i < iterations; i++) decay1 (); flushimage(display, 1); if(ecanmouse()) { m = emouse(); if(m.buttons&4) { if(emenuhit(3, &m, &menu) == 0) exits(0); } } if (delay) sleep (delay); } } void eresized(int new) { if(new && getwindow(display, Refnone) < 0) { sysfatal("can't reattach to window: %r"); } if(scrimg != nil) freeimage(scrimg); scrimg = squeeze(scrbuf); if(scrimg == nil) sysfatal("unable to fit screenshot to window: %r"); init_decay(); draw(screen, screen->r, scrimg, nil, scrimg->r.min); } void main(int argc, char **argv) { USED(argc, argv); srand(time(0)); scrbuf = getscr(); if(scrbuf == nil) sysfatal("could not obtain screenshot: %r"); if(initdraw(nil, nil, "decayscreen") < 0) sysfatal("initdraw failed: %r"); einit(Emouse); eresized(0); screenhack(); }