b7004851d85aab09641235987fc35539dfc3b7be
[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_DOUBLE_BUFFER_EXTENSION
45 # include "xdbe.h"
46 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
47
48 char *progclass="Kumppa";
49
50 char *defaults [] ={
51         ".background:           black",
52         "*speed:                0.1",
53         "*delay:                10000",
54 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
55         /* leave this off by default, since it slows things down.  -- jwz. */
56         "*useDBE:               False",
57 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
58         0
59 };
60
61 XrmOptionDescRec options [] = {
62         {"-delay",".delay",XrmoptionSepArg,0},
63         {"-speed",".speed",XrmoptionSepArg,0},
64         {"-random",".random",XrmoptionIsArg,0},
65 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
66         {"-dbuf",".dbuf",XrmoptionIsArg,0},
67 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
68         {0,0,0,0}
69 };
70
71 const char colors[96]=
72         {0,0,255, 0,51,255, 0,102,255, 0,153,255, 0,204,255,
73         0,255,255,0,255,204, 0,255,153, 0,255,102, 0,255,51,
74         0,255,0, 51,255,0, 102,255,0, 153,255,0, 204,255,0,
75         255,255,0, 255,204,0, 255,153,0, 255,102,0, 255,51,0,
76         255,0,0, 255,0,51, 255,0,102, 255,0,153, 255,0,204,
77         255,0,255, 219,0,255, 182,0,255, 146,0,255, 109,0,255,
78         73,0,255, 37,0,255};
79 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},
80         {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},
81         {-0.02,-0.04,-0.13,34,20,15}};
82
83 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}};
84 static int coords[8];
85 static int ocoords[8]={0,0,0,0,0,0,0,0};
86
87 static Display *dpy;
88 static Window win[2];
89 static GC fgc[33];
90 static GC cgc;
91 static int sizx,sizy;
92 static int midx,midy;
93 static unsigned long delay;
94 static Bool cosilines=True;
95 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
96 static Bool usedouble=False;
97 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
98
99 static int *Xrotations;
100 static int *Yrotations;
101 static int *Xrottable;
102 static int *Yrottable;
103
104 static int *rotateX;
105 static int *rotateY;
106
107 static int rotsizeX,rotsizeY;
108 static int stateX,stateY;
109
110 static int rx,ry;
111
112
113 int Satnum(int maxi)
114 {
115 return (int)(maxi*frand(1));
116 }
117
118
119 void palaRotate(int x,int y)
120 {
121 int ax,ay,bx,by,cx,cy;
122
123 ax=rotateX[x];
124 ay=rotateY[y];
125 bx=rotateX[x+1]+2;
126 by=rotateY[y+1]+2;
127 cx=rotateX[x]-(y-ry)+x-rx;
128 cy=rotateY[y]+(x-rx)+y-ry;
129 if (cx<0)
130         {
131         ax-=cx;
132         cx=0;
133         }
134 if (cy<0)
135         {
136         ay-=cy;
137         cy=0;
138         }
139 if (cx+bx-ax>sizx) bx=ax-cx+sizx;
140 if (cy+by-ay>sizy) by=ay-cy+sizy;
141 if (ax<bx && ay<by)
142         XCopyArea(dpy,win[0],win[1],cgc,ax,ay,bx-ax,by-ay,cx,cy);
143 }
144
145
146 void rotate(void)
147 {
148 int x,y;
149 int dx,dy;
150
151 rx=Xrottable[stateX+1]-Xrottable[stateX];
152 ry=Yrottable[stateY+1]-Yrottable[stateY];
153
154
155 for (x=0;x<=rx;x++)
156         rotateX[x]=(x)?midx-1-Xrotations[Xrottable[stateX+1]-x]:0;
157 for (x=0;x<=rx;x++)
158         rotateX[x+rx+1]=(x==rx)?sizx-1:midx+Xrotations[Xrottable[stateX]+x];
159 for (y=0;y<=ry;y++)
160         rotateY[y]=(y)?midy-1-Yrotations[Yrottable[stateY+1]-y]:0;
161 for (y=0;y<=ry;y++)
162         rotateY[y+ry+1]=(y==ry)?sizy-1:midy+Yrotations[Yrottable[stateY]+y];
163
164 x=(rx>ry)?rx:ry;
165 for (dy=0;dy<(x+1)<<1;dy++)
166         for (dx=0;dx<(x+1)<<1;dx++)
167                 {
168                 y=(rx>ry)?ry-rx:0;
169                 if (dy+y>=0 && dy<(ry+1)<<1 && dx<(rx+1)<<1)
170                         if (dy+y+dx<=ry+rx && dy+y-dx<=ry-rx)
171                                 {
172                                 palaRotate((rx<<1)+1-dx,dy+y);
173                                 palaRotate(dx,(ry<<1)+1-dy-y);
174                                 }
175                 y=(ry>rx)?rx-ry:0;
176                 if (dy+y>=0 && dx<(ry+1)<<1 && dy<(rx+1)<<1)
177                         if (dy+y+dx<=ry+rx && dx-dy-y>=ry-rx)
178                                 {
179                                 palaRotate(dy+y,dx);
180                                 palaRotate((rx<<1)+1-dy-y,(ry<<1)+1-dx);
181                                 }
182                 }
183 stateX++;
184 if (stateX==rotsizeX) stateX=0;
185 stateY++;
186 if (stateY==rotsizeY) stateY=0;
187 }
188
189
190
191 Bool make_rots(double xspeed,double yspeed)
192 {
193 int a,b,c,f,g,j,k=0,l;
194 double m,om,ok;
195 double d,ix,iy;
196 int maxi;
197
198 Bool *chks;
199
200 rotsizeX=(int)(2/xspeed+1);
201 ix=(double)(midx+1)/(double)(rotsizeX);
202 rotsizeY=(int)(2/yspeed+1);
203 iy=(double)(midy+1)/(double)(rotsizeY);
204
205 Xrotations=malloc((midx+2)*sizeof(unsigned int));
206 Xrottable=malloc((rotsizeX+1)*sizeof(unsigned int));
207 Yrotations=malloc((midy+2)*sizeof(unsigned int));
208 Yrottable=malloc((rotsizeY+1)*sizeof(unsigned int));
209 chks=malloc(((midx>midy)?midx:midy)*sizeof(Bool));
210 if (!Xrottable || !Yrottable || !Xrotations || !Yrotations || !chks) return False;
211
212
213 maxi=0;
214 c=0;
215 d=0;
216 g=0;
217 for (a=0;a<midx;a++) chks[a]=True;
218 for (a=0;a<rotsizeX;a++)
219         {
220         Xrottable[a]=c;
221         f=(int)(d+ix)-g;                                /*viivojen lkm.*/
222         g+=f;
223         if (g>midx)
224                 {
225                 f-=g-midx;
226                 g=midx;
227                 }
228         for (b=0;b<f;b++)
229                 {
230                 m=0;
231                 for (j=0;j<midx;j++)                    /*testi*/
232                         {
233                         if (chks[j])
234                                 {
235                                 om=0;
236                                 ok=1;
237                                 l=0;
238                                 while (j+l<midx && om+12*ok>m)
239                                         {
240                                         if (j-l>=0) if (chks[j-l]) om+=ok;
241                                                 else; else if (chks[l-j]) om+=ok;
242                                         if (chks[j+l]) om+=ok;
243                                         ok/=1.5;
244                                         l++;
245                                         }
246                                 if (om>=m)
247                                         {
248                                         k=j;
249                                         m=om;
250                                         }
251                                 }
252                         }
253                 chks[k]=False;
254                 l=c;
255                 while (l>=Xrottable[a])
256                         {
257                         if (l!=Xrottable[a]) Xrotations[l]=Xrotations[l-1];
258                         if (k>Xrotations[l] || l==Xrottable[a])
259                                 {
260                                 Xrotations[l]=k;
261                                 c++;
262                                 l=Xrottable[a];
263                                 }
264                         l--;
265                         }
266                 }
267         d+=ix;
268         if (maxi<c-Xrottable[a]) maxi=c-Xrottable[a];
269         }
270 Xrottable[a]=c;
271 rotateX=malloc((maxi+2)*sizeof(int)<<1);
272 if (!rotateX) return False;
273
274 maxi=0;
275 c=0;
276 d=0;
277 g=0;
278 for (a=0;a<midy;a++) chks[a]=True;
279 for (a=0;a<rotsizeY;a++)
280         {
281         Yrottable[a]=c;
282         f=(int)(d+iy)-g;                                /*viivojen lkm.*/
283         g+=f;
284         if (g>midy)
285                 {
286                 f-=g-midy;
287                 g=midy;
288                 }
289         for (b=0;b<f;b++)
290                 {
291                 m=0;
292                 for (j=0;j<midy;j++)                    /*testi*/
293                         {
294                         if (chks[j])
295                                 {
296                                 om=0;
297                                 ok=1;
298                                 l=0;
299                                 while (j+l<midy && om+12*ok>m)
300                                         {
301                                         if (j-l>=0) if (chks[j-l]) om+=ok;
302                                                 else; else if (chks[l-j]) om+=ok;
303                                         if (chks[j+l]) om+=ok;
304                                         ok/=1.5;
305                                         l++;
306                                         }
307                                 if (om>=m)
308                                         {
309                                         k=j;
310                                         m=om;
311                                         }
312                                 }
313                         }
314                 chks[k]=False;
315                 l=c;
316                 while (l>=Yrottable[a])
317                         {
318                         if (l!=Yrottable[a]) Yrotations[l]=Yrotations[l-1];
319                         if (k>Yrotations[l] || l==Yrottable[a])
320                                 {
321                                 Yrotations[l]=k;
322                                 c++;
323                                 l=Yrottable[a];
324                                 }
325                         l--;
326                         }
327
328                 }
329         d+=iy;
330         if (maxi<c-Yrottable[a]) maxi=c-Yrottable[a];
331         }
332 Yrottable[a]=c;
333 rotateY=malloc((maxi+2)*sizeof(int)<<1);
334 if (!rotateY) return False;
335
336 free(chks);
337 return (True);
338 }
339
340
341 Bool InitializeAll(void)
342 {
343 XGCValues xgcv;
344 XWindowAttributes xgwa;
345 XSetWindowAttributes xswa;
346 Colormap cmap;
347 XColor color;
348 int n,i;
349 double rspeed;
350
351 XGetWindowAttributes(dpy,win[0],&xgwa);
352 cmap=xgwa.colormap;
353 xswa.backing_store=Always;
354 XChangeWindowAttributes(dpy,win[0],CWBackingStore,&xswa);
355 xgcv.function=GXcopy;
356
357 xgcv.foreground=get_pixel_resource ("background", "Background", dpy, cmap);
358 fgc[32]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
359
360 n=0;
361 if (mono_p)
362         {
363         fgc[0]=fgc[32];
364         xgcv.foreground=get_pixel_resource ("foreground", "Foreground", dpy, cmap);
365         fgc[1]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
366         for (i=0;i<32;i+=2) fgc[i]=fgc[0];
367         for (i=1;i<32;i+=2) fgc[i]=fgc[1];
368         } else
369         for (i=0;i<32;i++)
370         {
371                 color.red=colors[n++]<<8;
372                 color.green=colors[n++]<<8;
373                 color.blue=colors[n++]<<8;
374                 color.flags=DoRed|DoGreen|DoBlue;
375                 XAllocColor(dpy,cmap,&color);
376                 xgcv.foreground=color.pixel;
377                 fgc[i]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
378         }
379 cgc=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
380 XSetGraphicsExposures(dpy,cgc,False);
381
382 if (get_string_resource("random","String")!=NULL && get_string_resource("random","String")[0]!=0) cosilines=False;
383
384 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
385  usedouble = True;
386  win[1] = xdbe_get_backbuffer (dpy, win[0], XdbeUndefined);
387  if (!win[1])
388    {
389      usedouble = False;
390      win[1] = win[0];
391    }
392 #endif /* HAVE_DOUBLE_BUFFER_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_DOUBLE_BUFFER_EXTENSION
421 XdbeSwapInfo xdswp;
422 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
423 int a,b,c=0,e;
424 float f;
425
426 dpy=d;
427 win[0]=w;
428 if (!InitializeAll()) return;
429
430 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
431 if (usedouble)
432         {
433         xdswp.swap_action=XdbeUndefined;
434         xdswp.swap_window=win[0];
435         }
436  else
437 #endif /* HAVE_DOUBLE_BUFFER_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_DOUBLE_BUFFER_EXTENSION
476         if (usedouble) XdbeSwapBuffers(dpy,&xdswp,1);
477 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
478         XSync(dpy, False);
479         screenhack_handle_events (dpy);
480         if (delay) usleep (delay);
481         }
482 }