1 /*
2
3 Copyright (C) Teemu Suutari (temisu@utu.fi) Feb 1998
4
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
12
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of the X Consortium shall
25 not be used in advertising or otherwise to promote the sale, use or
26 other dealings in this Software without prior written authorization
27 from the X Consortium.
28
29 */
30
31
32
33
34 /*
35
36 *** This is contest-version. Don't look any further, code is *very* ugly.
37
38 */
39
40 #include <math.h>
41 #include "screenhack.h"
42
43 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
44 # include "xdbe.h"
45 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
46
47 #undef countof
48 #define countof(x) (sizeof((x))/sizeof((*x)))
49
50 static const char *kumppa_defaults [] ={
51 ".background: black",
52 ".lowrez: true",
53 "*fpsSolid: true",
54 "*speed: 0.1",
55 "*delay: 10000",
56 "*random: True",
57 /* leave this off by default, since it slows things down. -- jwz. */
58 "*useDBE: False",
59 #ifdef HAVE_MOBILE
60 "*ignoreRotation: True",
61 #endif
62 0
63 };
64
65 static XrmOptionDescRec kumppa_options [] = {
66 {"-delay", ".delay", XrmoptionSepArg, 0 },
67 {"-speed", ".speed", XrmoptionSepArg, 0 },
68 {"-random", ".random", XrmoptionNoArg, "True" },
69 {"-no-random", ".random", XrmoptionNoArg, "False" },
70 {"-db", ".useDBE", XrmoptionNoArg, "True" },
71 {"-no-db", ".useDBE", XrmoptionNoArg, "False" },
72 {0,0,0,0}
73 };
74
75 static const unsigned char colors[96]=
76 {0,0,255, 0,51,255, 0,102,255, 0,153,255, 0,204,255,
77 0,255,255,0,255,204, 0,255,153, 0,255,102, 0,255,51,
78 0,255,0, 51,255,0, 102,255,0, 153,255,0, 204,255,0,
79 255,255,0, 255,204,0, 255,153,0, 255,102,0, 255,51,0,
80 255,0,0, 255,0,51, 255,0,102, 255,0,153, 255,0,204,
81 255,0,255, 219,0,255, 182,0,255, 146,0,255, 109,0,255,
82 73,0,255, 37,0,255};
83 static const float cosinus[8][6]=
84 {{-0.07,0.12,-0.06,32,25,37},{0.08,-0.03,0.05,51,46,32},{0.12,0.07,-0.13,27,45,36},
85 {0.05,-0.04,-0.07,36,27,39},{-0.02,-0.07,0.1,21,43,42},{-0.11,0.06,0.02,51,25,34},{0.04,-0.15,0.02,42,32,25},
86 {-0.02,-0.04,-0.13,34,20,15}};
87
88
89 struct state {
90 Display *dpy;
91 Window win[2];
92
93 float acosinus[8][3];
94 int coords[8];
95 int ocoords[8];
96
97 GC fgc[33];
98 GC cgc;
99 int sizx,sizy;
100 int midx,midy;
101 unsigned long delay;
102 Bool cosilines;
103
104 int *Xrotations;
105 int *Yrotations;
106 int *Xrottable;
107 int *Yrottable;
108
109 int *rotateX;
110 int *rotateY;
111
112 int rotsizeX,rotsizeY;
113 int stateX,stateY;
114
115 int rx,ry;
116
117 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
118 XdbeSwapInfo xdswp;
119 Bool usedouble;
120 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
121
122 int draw_count;
123 };
124
125
Satnum(int maxi)126 static int Satnum(int maxi)
127 {
128 return (int)(maxi*frand(1));
129 }
130
131
palaRotate(struct state * st,int x,int y)132 static void palaRotate(struct state *st, int x,int y)
133 {
134 int ax,ay,bx,by,cx,cy;
135
136 ax=st->rotateX[x];
137 ay=st->rotateY[y];
138 bx=st->rotateX[x+1]+2;
139 by=st->rotateY[y+1]+2;
140 cx=st->rotateX[x]-(y-st->ry)+x-st->rx;
141 cy=st->rotateY[y]+(x-st->rx)+y-st->ry;
142 if (cx<0)
143 {
144 ax-=cx;
145 cx=0;
146 }
147 if (cy<0)
148 {
149 ay-=cy;
150 cy=0;
151 }
152 if (cx+bx-ax>st->sizx) bx=ax-cx+st->sizx;
153 if (cy+by-ay>st->sizy) by=ay-cy+st->sizy;
154 if (ax<bx && ay<by)
155 XCopyArea(st->dpy,st->win[0],st->win[1],st->cgc,ax,ay,bx-ax,by-ay,cx,cy);
156 }
157
158
rotate(struct state * st)159 static void rotate(struct state *st)
160 {
161 int x,y;
162 int dx,dy;
163
164 st->rx=st->Xrottable[st->stateX+1]-st->Xrottable[st->stateX];
165 st->ry=st->Yrottable[st->stateY+1]-st->Yrottable[st->stateY];
166
167
168 for (x=0;x<=st->rx;x++)
169 st->rotateX[x]=(x)?st->midx-1-st->Xrotations[st->Xrottable[st->stateX+1]-x]:0;
170 for (x=0;x<=st->rx;x++)
171 st->rotateX[x+st->rx+1]=(x==st->rx)?st->sizx-1:st->midx+st->Xrotations[st->Xrottable[st->stateX]+x];
172 for (y=0;y<=st->ry;y++)
173 st->rotateY[y]=(y)?st->midy-1-st->Yrotations[st->Yrottable[st->stateY+1]-y]:0;
174 for (y=0;y<=st->ry;y++)
175 st->rotateY[y+st->ry+1]=(y==st->ry)?st->sizy-1:st->midy+st->Yrotations[st->Yrottable[st->stateY]+y];
176
177 x=(st->rx>st->ry)?st->rx:st->ry;
178 for (dy=0;dy<(x+1)<<1;dy++)
179 for (dx=0;dx<(x+1)<<1;dx++)
180 {
181 y=(st->rx>st->ry)?st->ry-st->rx:0;
182 if (dy+y>=0 && dy<(st->ry+1)<<1 && dx<(st->rx+1)<<1)
183 if (dy+y+dx<=st->ry+st->rx && dy+y-dx<=st->ry-st->rx)
184 {
185 palaRotate(st, (st->rx<<1)+1-dx,dy+y);
186 palaRotate(st, dx,(st->ry<<1)+1-dy-y);
187 }
188 y=(st->ry>st->rx)?st->rx-st->ry:0;
189 if (dy+y>=0 && dx<(st->ry+1)<<1 && dy<(st->rx+1)<<1)
190 if (dy+y+dx<=st->ry+st->rx && dx-dy-y>=st->ry-st->rx)
191 {
192 palaRotate(st, dy+y,dx);
193 palaRotate(st, (st->rx<<1)+1-dy-y,(st->ry<<1)+1-dx);
194 }
195 }
196 st->stateX++;
197 if (st->stateX==st->rotsizeX) st->stateX=0;
198 st->stateY++;
199 if (st->stateY==st->rotsizeY) st->stateY=0;
200 }
201
202
203
make_rots(struct state * st,double xspeed,double yspeed)204 static Bool make_rots(struct state *st, double xspeed,double yspeed)
205 {
206 int a,b,c,f,g,j,k=0,l;
207 double m,om,ok;
208 double d,ix,iy;
209 int maxi;
210
211 Bool *chks;
212
213 st->rotsizeX=(int)(2/xspeed+1);
214 ix=(double)(st->midx+1)/(double)(st->rotsizeX);
215 st->rotsizeY=(int)(2/yspeed+1);
216 iy=(double)(st->midy+1)/(double)(st->rotsizeY);
217
218 st->Xrotations=malloc((st->midx+2)*sizeof(int));
219 st->Xrottable=malloc((st->rotsizeX+1)*sizeof(int));
220 st->Yrotations=malloc((st->midy+2)*sizeof(int));
221 st->Yrottable=malloc((st->rotsizeY+1)*sizeof(int));
222 chks=malloc(((st->midx>st->midy)?st->midx:st->midy)*sizeof(Bool));
223 if (!st->Xrottable || !st->Yrottable || !st->Xrotations || !st->Yrotations || !chks) return False;
224
225
226 maxi=0;
227 c=0;
228 d=0;
229 g=0;
230 for (a=0;a<st->midx;a++) chks[a]=True;
231 for (a=0;a<st->rotsizeX;a++)
232 {
233 st->Xrottable[a]=c;
234 f=(int)(d+ix)-g; /*viivojen lkm.*/
235 g+=f;
236 if (g>st->midx)
237 {
238 f-=g-st->midx;
239 g=st->midx;
240 }
241 for (b=0;b<f;b++)
242 {
243 m=0;
244 for (j=0;j<st->midx;j++) /*testi*/
245 {
246 if (chks[j])
247 {
248 om=0;
249 ok=1;
250 l=0;
251 while (j+l<st->midx && om+12*ok>m)
252 {
253 if (j-l>=0) if (chks[j-l]) om+=ok;
254 else; else if (chks[l-j]) om+=ok;
255 if (chks[j+l]) om+=ok;
256 ok/=1.5;
257 l++;
258 }
259 if (om>=m)
260 {
261 k=j;
262 m=om;
263 }
264 }
265 }
266 chks[k]=False;
267 l=c;
268 while (l>=st->Xrottable[a])
269 {
270 if (l!=st->Xrottable[a]) st->Xrotations[l]=st->Xrotations[l-1];
271 if (k>st->Xrotations[l] || l==st->Xrottable[a])
272 {
273 st->Xrotations[l]=k;
274 c++;
275 l=st->Xrottable[a];
276 }
277 l--;
278 }
279 }
280 d+=ix;
281 if (maxi<c-st->Xrottable[a]) maxi=c-st->Xrottable[a];
282 }
283 st->Xrottable[a]=c;
284 st->rotateX=malloc((maxi+2)*sizeof(int)<<1);
285 if (!st->rotateX) return False;
286
287 maxi=0;
288 c=0;
289 d=0;
290 g=0;
291 for (a=0;a<st->midy;a++) chks[a]=True;
292 for (a=0;a<st->rotsizeY;a++)
293 {
294 st->Yrottable[a]=c;
295 f=(int)(d+iy)-g; /*viivojen lkm.*/
296 g+=f;
297 if (g>st->midy)
298 {
299 f-=g-st->midy;
300 g=st->midy;
301 }
302 for (b=0;b<f;b++)
303 {
304 m=0;
305 for (j=0;j<st->midy;j++) /*testi*/
306 {
307 if (chks[j])
308 {
309 om=0;
310 ok=1;
311 l=0;
312 while (j+l<st->midy && om+12*ok>m)
313 {
314 if (j-l>=0) if (chks[j-l]) om+=ok;
315 else; else if (chks[l-j]) om+=ok;
316 if (chks[j+l]) om+=ok;
317 ok/=1.5;
318 l++;
319 }
320 if (om>=m)
321 {
322 k=j;
323 m=om;
324 }
325 }
326 }
327 chks[k]=False;
328 l=c;
329 while (l>=st->Yrottable[a])
330 {
331 if (l!=st->Yrottable[a]) st->Yrotations[l]=st->Yrotations[l-1];
332 if (k>st->Yrotations[l] || l==st->Yrottable[a])
333 {
334 st->Yrotations[l]=k;
335 c++;
336 l=st->Yrottable[a];
337 }
338 l--;
339 }
340
341 }
342 d+=iy;
343 if (maxi<c-st->Yrottable[a]) maxi=c-st->Yrottable[a];
344 }
345 st->Yrottable[a]=c;
346 st->rotateY=malloc((maxi+2)*sizeof(int)<<1);
347 if (!st->rotateY) return False;
348
349 free(chks);
350 return (True);
351 }
352
353
InitializeAll(struct state * st)354 static Bool InitializeAll(struct state *st)
355 {
356 XGCValues xgcv;
357 XWindowAttributes xgwa;
358 /* XSetWindowAttributes xswa;*/
359 Colormap cmap;
360 XColor color;
361 int n,i;
362 double rspeed;
363
364 st->cosilines = True;
365
366 XGetWindowAttributes(st->dpy,st->win[0],&xgwa);
367 cmap=xgwa.colormap;
368 /* xswa.backing_store=Always;
369 XChangeWindowAttributes(st->dpy,st->win[0],CWBackingStore,&xswa);*/
370 xgcv.function=GXcopy;
371
372 xgcv.foreground=get_pixel_resource (st->dpy, cmap, "background", "Background");
373 st->fgc[32]=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv);
374
375 n=0;
376 if (mono_p)
377 {
378 st->fgc[0]=st->fgc[32];
379 xgcv.foreground=get_pixel_resource (st->dpy, cmap, "foreground", "Foreground");
380 st->fgc[1]=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv);
381 for (i=0;i<32;i+=2) st->fgc[i]=st->fgc[0];
382 for (i=1;i<32;i+=2) st->fgc[i]=st->fgc[1];
383 } else
384 for (i=0;i<32;i++)
385 {
386 color.red=colors[n++]<<8;
387 color.green=colors[n++]<<8;
388 color.blue=colors[n++]<<8;
389 color.flags=DoRed|DoGreen|DoBlue;
390 XAllocColor(st->dpy,cmap,&color);
391 xgcv.foreground=color.pixel;
392 st->fgc[i]=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv);
393 }
394 st->cgc=XCreateGC(st->dpy,st->win[0],GCForeground|GCFunction,&xgcv);
395 XSetGraphicsExposures(st->dpy,st->cgc,False);
396
397 st->cosilines = get_boolean_resource(st->dpy, "random","Boolean");
398
399 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
400 if (get_boolean_resource (st->dpy, "useDBE", "Boolean"))
401 st->usedouble = True;
402 st->win[1] = xdbe_get_backbuffer (st->dpy, st->win[0], XdbeUndefined);
403 if (!st->win[1])
404 {
405 st->usedouble = False;
406 st->win[1] = st->win[0];
407 }
408 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
409
410 st->delay=get_integer_resource(st->dpy, "delay","Integer");
411 rspeed=get_float_resource(st->dpy, "speed","Float");
412 if (rspeed<0.0001 || rspeed>0.2)
413 {
414 fprintf(stderr,"Speed not in valid range! (0.0001 - 0.2), using 0.1 \n");
415 rspeed=0.1;
416 }
417
418 st->sizx=xgwa.width;
419 st->sizy=xgwa.height;
420 st->midx=st->sizx>>1;
421 st->midy=st->sizy>>1;
422 st->stateX=0;
423 st->stateY=0;
424
425 if (!make_rots(st,rspeed,rspeed))
426 {
427 fprintf(stderr,"Not enough memory for tables!\n");
428 return False;
429 }
430 return True;
431 }
432
433 static void *
kumppa_init(Display * d,Window w)434 kumppa_init (Display *d, Window w)
435 {
436 struct state *st = (struct state *) calloc (1, sizeof(*st));
437 st->dpy=d;
438 st->win[0]=w;
439 if (!InitializeAll(st)) abort();
440
441 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
442 if (st->usedouble)
443 {
444 st->xdswp.swap_action=XdbeUndefined;
445 st->xdswp.swap_window=st->win[0];
446 }
447 else
448 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
449 st->win[1]=st->win[0];
450
451 return st;
452 }
453
454 static unsigned long
kumppa_draw(Display * d,Window w,void * closure)455 kumppa_draw (Display *d, Window w, void *closure)
456 {
457 struct state *st = (struct state *) closure;
458 if (st->cosilines)
459 {
460 int a;
461 st->draw_count++;
462 for (a=0;a<8;a++)
463 {
464 float f=0;
465 int b;
466 for (b=0;b<3;b++)
467 {
468 st->acosinus[a][b]+=cosinus[a][b];
469 f+=cosinus[a][b+3]*sin((double)st->acosinus[a][b]);
470 }
471 st->coords[a]=(int)f;
472 }
473 for (a=0;a<4;a++)
474 {
475 XDrawLine(st->dpy,st->win[0],(mono_p)?st->fgc[1]:st->fgc[((a<<2)+st->draw_count)&31],st->midx+st->ocoords[a<<1],st->midy+st->ocoords[(a<<1)+1]
476 ,st->midx+st->coords[a<<1],st->midy+st->coords[(a<<1)+1]);
477 st->ocoords[a<<1]=st->coords[a<<1];
478 st->ocoords[(a<<1)+1]=st->coords[(a<<1)+1];
479 }
480
481 } else {
482 int e;
483 for (e=0;e<8;e++)
484 {
485 int a=Satnum(50);
486 int b;
487 if (a>=32) a=32;
488 b=Satnum(32)-16+st->midx;
489 st->draw_count=Satnum(32)-16+st->midy;
490 XFillRectangle(st->dpy,st->win[0],st->fgc[a],b,st->draw_count,2,2);
491 }
492 }
493 XFillRectangle(st->dpy,st->win[0],st->fgc[32],st->midx-2,st->midy-2,4,4);
494 rotate(st);
495 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
496 if (st->usedouble) XdbeSwapBuffers(st->dpy,&st->xdswp,1);
497 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
498
499 return st->delay;
500 }
501
502
503 static void
kumppa_reshape(Display * dpy,Window window,void * closure,unsigned int w,unsigned int h)504 kumppa_reshape (Display *dpy, Window window, void *closure,
505 unsigned int w, unsigned int h)
506 {
507 struct state *st = (struct state *) closure;
508 st->sizx=w;
509 st->sizy=h;
510 st->midx=st->sizx>>1;
511 st->midy=st->sizy>>1;
512 st->stateX=0;
513 st->stateY=0;
514 }
515
516 static Bool
kumppa_event(Display * dpy,Window window,void * closure,XEvent * event)517 kumppa_event (Display *dpy, Window window, void *closure, XEvent *event)
518 {
519 return False;
520 }
521
522 static void
kumppa_free(Display * dpy,Window window,void * closure)523 kumppa_free (Display *dpy, Window window, void *closure)
524 {
525 struct state *st = (struct state *) closure;
526 int i;
527 for (i = 0; i < countof(st->fgc); i++)
528 if (st->fgc[i]) XFreeGC (dpy, st->fgc[i]);
529 XFreeGC (dpy, st->cgc);
530 free (st->Xrotations);
531 free (st->Yrotations);
532 free (st->Xrottable);
533 free (st->Yrottable);
534 free (st->rotateX);
535 free (st->rotateY);
536 free (st);
537 }
538
539 XSCREENSAVER_MODULE ("Kumppa", kumppa)
540