http://ftp.x.org/contrib/applications/xscreensaver-2.24.tar.gz
[xscreensaver] / hacks / kumppa.c
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
41 #include <math.h>
42 #include "screenhack.h"
43
44 #ifdef HAVE_XDBE_EXTENSION
45 # include <X11/extensions/Xdbe.h>
46 #endif /* HAVE_XDBE_EXTENSION */
47
48 char *progclass="Kumppa";
49
50 char *defaults [] ={
51         ".background:           black",
52         "*speed:                0.1",
53         "*delay:                0",
54         0
55 };
56
57 XrmOptionDescRec options [] = {
58         {"-delay",".delay",XrmoptionSepArg,0},
59         {"-speed",".speed",XrmoptionSepArg,0},
60         {"-random",".random",XrmoptionIsArg,0},
61 #ifdef HAVE_XDBE_EXTENSION
62         {"-dbuf",".dbuf",XrmoptionIsArg,0},
63 #endif /* HAVE_XDBE_EXTENSION */
64         {0,0,0,0}
65 };
66
67 const char colors[96]=
68         {0,0,255, 0,51,255, 0,102,255, 0,153,255, 0,204,255,
69         0,255,255,0,255,204, 0,255,153, 0,255,102, 0,255,51,
70         0,255,0, 51,255,0, 102,255,0, 153,255,0, 204,255,0,
71         255,255,0, 255,204,0, 255,153,0, 255,102,0, 255,51,0,
72         255,0,0, 255,0,51, 255,0,102, 255,0,153, 255,0,204,
73         255,0,255, 219,0,255, 182,0,255, 146,0,255, 109,0,255,
74         73,0,255, 37,0,255};
75 const float cosinus[8][6]={{-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},
76         {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},
77         {-0.02,-0.04,-0.13,34,20,15}};
78
79 static float acosinus[8][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
80 static int coords[8];
81 static int ocoords[8]={0,0,0,0,0,0,0,0};
82
83 static Display *dpy;
84 static Window win[2];
85 static GC fgc[33];
86 static GC cgc;
87 static int sizx,sizy;
88 static int midx,midy;
89 static unsigned long delay;
90 static Bool cosilines=True;
91 #ifdef HAVE_XDBE_EXTENSION
92 static Bool usedouble=False;
93 #endif /* HAVE_XDBE_EXTENSION */
94
95 static int *Xrotations;
96 static int *Yrotations;
97 static int *Xrottable;
98 static int *Yrottable;
99
100 static int *rotateX;
101 static int *rotateY;
102
103 static int rotsizeX,rotsizeY;
104 static int stateX,stateY;
105
106 static int rx,ry;
107
108
109 int Satnum(int maxi)
110 {
111 return (int)(maxi*frand(1));
112 }
113
114
115 void palaRotate(int x,int y)
116 {
117 int ax,ay,bx,by,cx,cy;
118
119 ax=rotateX[x];
120 ay=rotateY[y];
121 bx=rotateX[x+1]+2;
122 by=rotateY[y+1]+2;
123 cx=rotateX[x]-(y-ry)+x-rx;
124 cy=rotateY[y]+(x-rx)+y-ry;
125 if (cx<0)
126         {
127         ax-=cx;
128         cx=0;
129         }
130 if (cy<0)
131         {
132         ay-=cy;
133         cy=0;
134         }
135 if (cx+bx-ax>sizx) bx=ax-cx+sizx;
136 if (cy+by-ay>sizy) by=ay-cy+sizy;
137 if (ax<bx && ay<by)
138         XCopyArea(dpy,win[0],win[1],cgc,ax,ay,bx-ax,by-ay,cx,cy);
139 }
140
141
142 void rotate(void)
143 {
144 int x,y;
145 int dx,dy;
146
147 rx=Xrottable[stateX+1]-Xrottable[stateX];
148 ry=Yrottable[stateX+1]-Yrottable[stateY];
149
150
151 for (x=0;x<=rx;x++)
152         rotateX[x]=(x)?midx-1-Xrotations[Xrottable[stateX+1]-x]:0;
153 for (x=0;x<=rx;x++)
154         rotateX[x+rx+1]=(x==rx)?sizx-1:midx+Xrotations[Xrottable[stateX]+x];
155 for (y=0;y<=ry;y++)
156         rotateY[y]=(y)?midy-1-Yrotations[Yrottable[stateY+1]-y]:0;
157 for (y=0;y<=ry;y++)
158         rotateY[y+ry+1]=(y==ry)?sizy-1:midy+Yrotations[Yrottable[stateY]+y];
159
160 x=(rx>ry)?rx:ry;
161 for (dy=0;dy<(x+1)<<1;dy++)
162         for (dx=0;dx<(x+1)<<1;dx++)
163                 {
164                 y=(rx>ry)?ry-rx:0;
165                 if (dy+y>=0 && dy<(ry+1)<<1 && dx<(rx+1)<<1)
166                         if (dy+y+dx<=ry+rx && dy+y-dx<=ry-rx)
167                                 {
168                                 palaRotate((rx<<1)+1-dx,dy+y);
169                                 palaRotate(dx,(ry<<1)+1-dy-y);
170                                 }
171                 y=(ry>rx)?rx-ry:0;
172                 if (dy+y>=0 && dx<(ry+1)<<1 && dy<(rx+1)<<1)
173                         if (dy+y+dx<=ry+rx && dx-dy-y>=ry-rx)
174                                 {
175                                 palaRotate(dy+y,dx);
176                                 palaRotate((rx<<1)+1-dy-y,(ry<<1)+1-dx);
177                                 }
178                 }
179 stateX++;
180 if (stateX==rotsizeX) stateX=0;
181 stateY++;
182 if (stateY==rotsizeY) stateY=0;
183 }
184
185
186
187 Bool make_rots(double xspeed,double yspeed)
188 {
189 int a,b,c,f,g,j,k,l;
190 double m,om,ok;
191 double d,ix,iy;
192 int maxi;
193
194 Bool *chks;
195
196 rotsizeX=(int)(2/xspeed+1);
197 ix=(double)(midx+1)/(double)(rotsizeX);
198 rotsizeY=(int)(2/yspeed+1);
199 iy=(double)(midy+1)/(double)(rotsizeY);
200
201 Xrotations=malloc((midx+2)*sizeof(unsigned int));
202 Xrottable=malloc((rotsizeX+1)*sizeof(unsigned int));
203 Yrotations=malloc((midy+2)*sizeof(unsigned int));
204 Yrottable=malloc((rotsizeY+1)*sizeof(unsigned int));
205 chks=malloc(((midx>midy)?midx:midy)*sizeof(Bool));
206 if (!Xrottable || !Yrottable || !Xrotations || !Yrotations || !chks) return False;
207
208
209 maxi=0;
210 c=0;
211 d=0;
212 g=0;
213 for (a=0;a<midx;a++) chks[a]=True;
214 for (a=0;a<rotsizeX;a++)
215         {
216         Xrottable[a]=c;
217         f=(int)(d+ix)-g;                                /*viivojen lkm.*/
218         g+=f;
219         if (g>midx)
220                 {
221                 f-=g-midx;
222                 g=midx;
223                 }
224         for (b=0;b<f;b++)
225                 {
226                 m=0;
227                 for (j=0;j<midx;j++)                    /*testi*/
228                         {
229                         if (chks[j])
230                                 {
231                                 om=0;
232                                 ok=1;
233                                 l=0;
234                                 while (j+l<midx && om+12*ok>m)
235                                         {
236                                         if (j-l>=0) if (chks[j-l]) om+=ok;
237                                                 else; else if (chks[l-j]) om+=ok;
238                                         if (chks[j+l]) om+=ok;
239                                         ok/=1.5;
240                                         l++;
241                                         }
242                                 if (om>=m)
243                                         {
244                                         k=j;
245                                         m=om;
246                                         }
247                                 }
248                         }
249                 chks[k]=False;
250                 l=c;
251                 while (l>=Xrottable[a])
252                         {
253                         if (l!=Xrottable[a]) Xrotations[l]=Xrotations[l-1];
254                         if (k>Xrotations[l] || l==Xrottable[a])
255                                 {
256                                 Xrotations[l]=k;
257                                 c++;
258                                 l=Xrottable[a];
259                                 }
260                         l--;
261                         }
262                 }
263         d+=ix;
264         if (maxi<c-Xrottable[a]) maxi=c-Xrottable[a];
265         }
266 Xrottable[a]=c;
267 rotateX=malloc((maxi+2)*sizeof(int)<<1);
268 if (!rotateX) return False;
269
270 maxi=0;
271 c=0;
272 d=0;
273 g=0;
274 for (a=0;a<midy;a++) chks[a]=True;
275 for (a=0;a<rotsizeY;a++)
276         {
277         Yrottable[a]=c;
278         f=(int)(d+iy)-g;                                /*viivojen lkm.*/
279         g+=f;
280         if (g>midy)
281                 {
282                 f-=g-midy;
283                 g=midy;
284                 }
285         for (b=0;b<f;b++)
286                 {
287                 m=0;
288                 for (j=0;j<midy;j++)                    /*testi*/
289                         {
290                         if (chks[j])
291                                 {
292                                 om=0;
293                                 ok=1;
294                                 l=0;
295                                 while (j+l<midy && om+12*ok>m)
296                                         {
297                                         if (j-l>=0) if (chks[j-l]) om+=ok;
298                                                 else; else if (chks[l-j]) om+=ok;
299                                         if (chks[j+l]) om+=ok;
300                                         ok/=1.5;
301                                         l++;
302                                         }
303                                 if (om>=m)
304                                         {
305                                         k=j;
306                                         m=om;
307                                         }
308                                 }
309                         }
310                 chks[k]=False;
311                 l=c;
312                 while (l>=Yrottable[a])
313                         {
314                         if (l!=Yrottable[a]) Yrotations[l]=Yrotations[l-1];
315                         if (k>Yrotations[l] || l==Yrottable[a])
316                                 {
317                                 Yrotations[l]=k;
318                                 c++;
319                                 l=Yrottable[a];
320                                 }
321                         l--;
322                         }
323
324                 }
325         d+=iy;
326         if (maxi<c-Yrottable[a]) maxi=c-Yrottable[a];
327         }
328 Yrottable[a]=c;
329 rotateY=malloc((maxi+2)*sizeof(int)<<1);
330 if (!rotateY) return False;
331
332 free(chks);
333 return (True);
334 }
335
336
337 Bool InitializeAll(void)
338 {
339 XGCValues xgcv;
340 XWindowAttributes xgwa;
341 XSetWindowAttributes xswa;
342 Colormap cmap;
343 XColor color;
344 int n,i;
345 double rspeed;
346
347 XGetWindowAttributes(dpy,win[0],&xgwa);
348 cmap=xgwa.colormap;
349 xswa.backing_store=Always;
350 XChangeWindowAttributes(dpy,win[0],CWBackingStore,&xswa);
351 xgcv.function=GXcopy;
352
353 xgcv.foreground=get_pixel_resource ("background", "Background", dpy, cmap);
354 fgc[32]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
355
356 n=0;
357 if (mono_p)
358         {
359         fgc[0]=fgc[32];
360         xgcv.foreground=get_pixel_resource ("foreground", "Foreground", dpy, cmap);
361         fgc[1]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
362         for (i=0;i<32;i+=2) fgc[i]=fgc[0];
363         for (i=1;i<32;i+=2) fgc[i]=fgc[1];
364         } else
365         for (i=0;i<32;i++)
366         {
367                 color.red=colors[n++]<<8;
368                 color.green=colors[n++]<<8;
369                 color.blue=colors[n++]<<8;
370                 color.flags=DoRed|DoGreen|DoBlue;
371                 XAllocColor(dpy,cmap,&color);
372                 xgcv.foreground=color.pixel;
373                 fgc[i]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
374         }
375 cgc=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
376 XSetGraphicsExposures(dpy,cgc,False);
377
378 if (get_string_resource("random","String")!=NULL && get_string_resource("random","String")[0]!=0) cosilines=False;
379
380 #ifdef HAVE_XDBE_EXTENSION
381 if (get_string_resource("dbuf","String")!=NULL && get_string_resource("dbuf","String")[0]!=0) usedouble=True;
382 if (usedouble)
383         {
384         XdbeQueryExtension(dpy,&n,&i);
385         if (n==0 && i==0)
386                 {
387                 fprintf(stderr,"Double buffer extension not supported!\n");
388                 usedouble=False;
389                 }
390         }
391 if (usedouble) win[1]=XdbeAllocateBackBufferName(dpy,win[0],XdbeUndefined);
392 #endif /* HAVE_XDBE_EXTENSION */
393
394 delay=get_integer_resource("delay","Integer");
395 rspeed=get_float_resource("speed","Float");
396 if (rspeed<0.0001 || rspeed>0.2)
397         {
398         fprintf(stderr,"Speed not in valid range! (0.0001 - 0.2), using 0.1 \n");
399         rspeed=0.1;
400         }
401
402 sizx=xgwa.width;
403 sizy=xgwa.height;
404 midx=sizx>>1;
405 midy=sizy>>1;
406 stateX=0;
407 stateY=0;
408
409 if (!make_rots(rspeed,rspeed))
410         {
411         fprintf(stderr,"Not enough memory for tables!\n");
412         return False;
413         }
414 return True;
415 }
416
417
418 void screenhack(Display *d, Window w)
419 {
420 #ifdef HAVE_XDBE_EXTENSION
421 XdbeSwapInfo xdswp;
422 #endif /* HAVE_XDBE_EXTENSION */
423 int a,b,c,e;
424 float f;
425
426 dpy=d;
427 win[0]=w;
428 if (!InitializeAll()) return;
429
430 #ifdef HAVE_XDBE_EXTENSION
431 if (usedouble)
432         {
433         xdswp.swap_action=XdbeUndefined;
434         xdswp.swap_window=win[0];
435         }
436  else
437 #endif /* HAVE_XDBE_EXTENSION */
438    win[1]=win[0];
439
440 while (0==0)
441         {
442         if (cosilines)
443                 {
444                 c++;
445                 for (a=0;a<8;a++)
446                         {
447                         f=0;
448                         for (b=0;b<3;b++)
449                                 {
450                                 acosinus[a][b]+=cosinus[a][b];
451                                 f+=cosinus[a][b+3]*sin((double)acosinus[a][b]);
452                                 }
453                         coords[a]=(int)f;
454                         }
455                 for (a=0;a<4;a++)
456                         {
457                         XDrawLine(dpy,win[0],(mono_p)?fgc[1]:fgc[((a<<2)+c)&31],midx+ocoords[a<<1],midy+ocoords[(a<<1)+1]
458                         ,midx+coords[a<<1],midy+coords[(a<<1)+1]);
459                         ocoords[a<<1]=coords[a<<1];
460                         ocoords[(a<<1)+1]=coords[(a<<1)+1];
461                         }
462
463                 } else {
464                 for (e=0;e<8;e++)
465                         {
466                         a=Satnum(50);
467                         if (a>=32) a=32;
468                         b=Satnum(32)-16+midx;
469                         c=Satnum(32)-16+midy;
470                         XFillRectangle(dpy,win[0],fgc[a],b,c,2,2);
471                         }
472                 }
473         XFillRectangle(dpy,win[0],fgc[32],midx-2,midy-2,4,4);
474         rotate();
475 #ifdef HAVE_XDBE_EXTENSION
476         if (usedouble) XdbeSwapBuffers(dpy,&xdswp,1);
477 #endif /* HAVE_XDBE_EXTENSION */
478         XSync(dpy,True);
479         if (delay) usleep (delay);
480         }
481 }