PageRenderTime 64ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 0ms

/xscreensaver-5.18/hacks/decayscreen.c

#
C | 380 lines | 288 code | 50 blank | 42 comment | 99 complexity | d225af29116e5afaf5e52d16028e80f6 MD5 | raw file
  1. /* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski <jwz@jwz.org>
  2. *
  3. * Permission to use, copy, modify, distribute, and sell this software and its
  4. * documentation for any purpose is hereby granted without fee, provided that
  5. * the above copyright notice appear in all copies and that both that
  6. * copyright notice and this permission notice appear in supporting
  7. * documentation. No representations are made about the suitability of this
  8. * software for any purpose. It is provided "as is" without express or
  9. * implied warranty.
  10. */
  11. /* decayscreen
  12. *
  13. * Based on slidescreen program from the xscreensaver application and the
  14. * decay program for Sun framebuffers. This is the comment from the decay.c
  15. * file:
  16. * decay.c
  17. * find the screen bitmap for the console and make it "decay" by
  18. * randomly shifting random rectangles by one pixelwidth at a time.
  19. *
  20. * by David Wald, 1988
  21. * rewritten by Natuerlich!
  22. * based on a similar "utility" on the Apollo ring at Yale.
  23. * X version by
  24. *
  25. * Vivek Khera <khera@cs.duke.edu>
  26. * 5-AUG-1993
  27. *
  28. * Hacked by jwz, 28-Nov-97 (sped up and added new motion directions)
  29. * R. Schultz
  30. * Added "melt" & "stretch" modes 28-Mar-1999
  31. *
  32. */
  33. #include "screenhack.h"
  34. struct state {
  35. Display *dpy;
  36. Window window;
  37. XWindowAttributes xgwa;
  38. Pixmap saved;
  39. int saved_w, saved_h;
  40. int sizex, sizey;
  41. int delay;
  42. int duration;
  43. GC gc;
  44. int mode;
  45. int random_p;
  46. time_t start_time;
  47. int fuzz_toggle;
  48. const int *current_bias;
  49. async_load_state *img_loader;
  50. };
  51. #define SHUFFLE 0
  52. #define UP 1
  53. #define LEFT 2
  54. #define RIGHT 3
  55. #define DOWN 4
  56. #define UPLEFT 5
  57. #define DOWNLEFT 6
  58. #define UPRIGHT 7
  59. #define DOWNRIGHT 8
  60. #define IN 9
  61. #define OUT 10
  62. #define MELT 11
  63. #define STRETCH 12
  64. #define FUZZ 13
  65. static void
  66. decayscreen_load_image (struct state *st)
  67. {
  68. XWindowAttributes xgwa;
  69. XGetWindowAttributes (st->dpy, st->window, &xgwa);
  70. st->sizex = xgwa.width;
  71. st->sizey = xgwa.height;
  72. if (st->img_loader) abort();
  73. st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
  74. st->window, 0, 0);
  75. }
  76. static void *
  77. decayscreen_init (Display *dpy, Window window)
  78. {
  79. struct state *st = (struct state *) calloc (1, sizeof(*st));
  80. XGCValues gcv;
  81. long gcflags;
  82. unsigned long bg;
  83. char *s;
  84. st->dpy = dpy;
  85. st->window = window;
  86. st->random_p = 0;
  87. s = get_string_resource(st->dpy, "mode", "Mode");
  88. if (s && !strcmp(s, "shuffle")) st->mode = SHUFFLE;
  89. else if (s && !strcmp(s, "up")) st->mode = UP;
  90. else if (s && !strcmp(s, "left")) st->mode = LEFT;
  91. else if (s && !strcmp(s, "right")) st->mode = RIGHT;
  92. else if (s && !strcmp(s, "down")) st->mode = DOWN;
  93. else if (s && !strcmp(s, "upleft")) st->mode = UPLEFT;
  94. else if (s && !strcmp(s, "downleft")) st->mode = DOWNLEFT;
  95. else if (s && !strcmp(s, "upright")) st->mode = UPRIGHT;
  96. else if (s && !strcmp(s, "downright")) st->mode = DOWNRIGHT;
  97. else if (s && !strcmp(s, "in")) st->mode = IN;
  98. else if (s && !strcmp(s, "out")) st->mode = OUT;
  99. else if (s && !strcmp(s, "melt")) st->mode = MELT;
  100. else if (s && !strcmp(s, "stretch")) st->mode = STRETCH;
  101. else if (s && !strcmp(s, "fuzz")) st->mode = FUZZ;
  102. else {
  103. if (s && *s && !!strcmp(s, "random"))
  104. fprintf(stderr, "%s: unknown mode %s\n", progname, s);
  105. st->random_p = 1;
  106. st->mode = random() % (FUZZ+1);
  107. }
  108. st->delay = get_integer_resource (st->dpy, "delay", "Integer");
  109. if (st->delay < 0) st->delay = 0;
  110. st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
  111. if (st->duration < 1) st->duration = 1;
  112. XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
  113. gcv.function = GXcopy;
  114. gcv.subwindow_mode = IncludeInferiors;
  115. bg = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background");
  116. gcv.foreground = bg;
  117. gcflags = GCForeground | GCFunction;
  118. if (use_subwindow_mode_p(st->xgwa.screen, st->window)) /* see grabscreen.c */
  119. gcflags |= GCSubwindowMode;
  120. st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
  121. st->start_time = time ((time_t) 0);
  122. decayscreen_load_image (st);
  123. return st;
  124. }
  125. /*
  126. * perform one iteration of decay
  127. */
  128. static unsigned long
  129. decayscreen_draw (Display *dpy, Window window, void *closure)
  130. {
  131. struct state *st = (struct state *) closure;
  132. int left, top, width, height, toleft, totop;
  133. #define L 101
  134. #define R 102
  135. #define U 103
  136. #define D 104
  137. static const int no_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
  138. static const int up_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
  139. static const int down_bias[] = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
  140. static const int left_bias[] = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
  141. static const int right_bias[] = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
  142. static const int upleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
  143. static const int downleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
  144. static const int upright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
  145. static const int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
  146. if (st->img_loader) /* still loading */
  147. {
  148. st->img_loader = load_image_async_simple (st->img_loader,
  149. 0, 0, 0, 0, 0);
  150. if (! st->img_loader) { /* just finished */
  151. st->start_time = time ((time_t) 0);
  152. if (st->random_p)
  153. st->mode = random() % (FUZZ+1);
  154. if (st->mode == MELT || st->mode == STRETCH)
  155. /* make sure screen eventually turns background color */
  156. XDrawLine (st->dpy, st->window, st->gc, 0, 0, st->sizex, 0);
  157. if (!st->saved) {
  158. st->saved = XCreatePixmap (st->dpy, st->window,
  159. st->sizex, st->sizey,
  160. st->xgwa.depth);
  161. st->saved_w = st->sizex;
  162. st->saved_h = st->sizey;
  163. }
  164. XCopyArea (st->dpy, st->window, st->saved, st->gc, 0, 0,
  165. st->sizex, st->sizey, 0, 0);
  166. }
  167. return st->delay;
  168. }
  169. if (!st->img_loader &&
  170. st->start_time + st->duration < time ((time_t) 0)) {
  171. decayscreen_load_image (st);
  172. }
  173. switch (st->mode) {
  174. case SHUFFLE: st->current_bias = no_bias; break;
  175. case UP: st->current_bias = up_bias; break;
  176. case LEFT: st->current_bias = left_bias; break;
  177. case RIGHT: st->current_bias = right_bias; break;
  178. case DOWN: st->current_bias = down_bias; break;
  179. case UPLEFT: st->current_bias = upleft_bias; break;
  180. case DOWNLEFT: st->current_bias = downleft_bias; break;
  181. case UPRIGHT: st->current_bias = upright_bias; break;
  182. case DOWNRIGHT: st->current_bias = downright_bias; break;
  183. case IN: st->current_bias = no_bias; break;
  184. case OUT: st->current_bias = no_bias; break;
  185. case MELT: st->current_bias = no_bias; break;
  186. case STRETCH: st->current_bias = no_bias; break;
  187. case FUZZ: st->current_bias = no_bias; break;
  188. default: abort();
  189. }
  190. #define nrnd(x) ((x) ? random() % (x) : x)
  191. if (st->mode == MELT || st->mode == STRETCH) {
  192. left = nrnd(st->sizex/2);
  193. top = nrnd(st->sizey);
  194. width = nrnd( st->sizex/2 ) + st->sizex/2 - left;
  195. height = nrnd(st->sizey - top);
  196. toleft = left;
  197. totop = top+1;
  198. } else if (st->mode == FUZZ) { /* By Vince Levey <vincel@vincel.org>;
  199. inspired by the "melt" mode of the
  200. "scrhack" IrisGL program by Paul Haeberli
  201. circa 1991. */
  202. left = nrnd(st->sizex - 1);
  203. top = nrnd(st->sizey - 1);
  204. st->fuzz_toggle = !st->fuzz_toggle;
  205. if (st->fuzz_toggle)
  206. {
  207. totop = top;
  208. height = 1;
  209. toleft = nrnd(st->sizex - 1);
  210. if (toleft > left)
  211. {
  212. width = toleft-left;
  213. toleft = left;
  214. left++;
  215. }
  216. else
  217. {
  218. width = left-toleft;
  219. left = toleft;
  220. toleft++;
  221. }
  222. }
  223. else
  224. {
  225. toleft = left;
  226. width = 1;
  227. totop = nrnd(st->sizey - 1);
  228. if (totop > top)
  229. {
  230. height = totop-top;
  231. totop = top;
  232. top++;
  233. }
  234. else
  235. {
  236. height = top-totop;
  237. top = totop;
  238. totop++;
  239. }
  240. }
  241. } else {
  242. left = nrnd(st->sizex - 1);
  243. top = nrnd(st->sizey);
  244. width = nrnd(st->sizex - left);
  245. height = nrnd(st->sizey - top);
  246. toleft = left;
  247. totop = top;
  248. if (st->mode == IN || st->mode == OUT) {
  249. int x = left+(width/2);
  250. int y = top+(height/2);
  251. int cx = st->sizex/2;
  252. int cy = st->sizey/2;
  253. if (st->mode == IN) {
  254. if (x > cx && y > cy) st->current_bias = upleft_bias;
  255. else if (x < cx && y > cy) st->current_bias = upright_bias;
  256. else if (x < cx && y < cy) st->current_bias = downright_bias;
  257. else /* (x > cx && y < cy)*/ st->current_bias = downleft_bias;
  258. } else {
  259. if (x > cx && y > cy) st->current_bias = downright_bias;
  260. else if (x < cx && y > cy) st->current_bias = downleft_bias;
  261. else if (x < cx && y < cy) st->current_bias = upleft_bias;
  262. else /* (x > cx && y < cy)*/ st->current_bias = upright_bias;
  263. }
  264. }
  265. switch (st->current_bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
  266. case L: toleft = left-1; break;
  267. case R: toleft = left+1; break;
  268. case U: totop = top-1; break;
  269. case D: totop = top+1; break;
  270. default: abort(); break;
  271. }
  272. }
  273. if (st->mode == STRETCH) {
  274. XCopyArea (st->dpy, st->window, st->window, st->gc, 0, st->sizey-top-2, st->sizex, top+1,
  275. 0, st->sizey-top-1);
  276. } else {
  277. XCopyArea (st->dpy, st->window, st->window, st->gc, left, top, width, height,
  278. toleft, totop);
  279. }
  280. #undef nrnd
  281. return st->delay;
  282. }
  283. static void
  284. decayscreen_reshape (Display *dpy, Window window, void *closure,
  285. unsigned int w, unsigned int h)
  286. {
  287. struct state *st = (struct state *) closure;
  288. XClearWindow (st->dpy, st->window);
  289. XCopyArea (st->dpy, st->saved, st->window, st->gc,
  290. 0, 0, st->saved_w, st->saved_h,
  291. (w - st->saved_w) / 2,
  292. (h - st->saved_h) / 2);
  293. st->sizex = w;
  294. st->sizey = h;
  295. }
  296. static Bool
  297. decayscreen_event (Display *dpy, Window window, void *closure, XEvent *event)
  298. {
  299. return False;
  300. }
  301. static void
  302. decayscreen_free (Display *dpy, Window window, void *closure)
  303. {
  304. struct state *st = (struct state *) closure;
  305. free (st);
  306. }
  307. static const char *decayscreen_defaults [] = {
  308. ".background: Black",
  309. ".foreground: Yellow",
  310. "*dontClearRoot: True",
  311. "*fpsSolid: True",
  312. #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
  313. "*visualID: Best",
  314. #endif
  315. "*delay: 10000",
  316. "*mode: random",
  317. "*duration: 120",
  318. 0
  319. };
  320. static XrmOptionDescRec decayscreen_options [] = {
  321. { "-delay", ".delay", XrmoptionSepArg, 0 },
  322. { "-mode", ".mode", XrmoptionSepArg, 0 },
  323. { "-duration", ".duration", XrmoptionSepArg, 0 },
  324. { 0, 0, 0, 0 }
  325. };
  326. XSCREENSAVER_MODULE ("DecayScreen", decayscreen)