http://ftp.aanet.ru/pub/Linux/X11/apps/xscreensaver-2.31.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[stateY+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 #ifdef HAVE_XDBE_EXTENSION
338 static XErrorHandler old_handler = 0;
339 static Bool got_BadMatch = False;
340 static int
341 BadMatch_ehandler (Display *dpy, XErrorEvent *error)
342 {
343   if (error->error_code == BadMatch) {
344     got_BadMatch = True;
345     return 0;
346   } else if (old_handler)
347     return old_handler(dpy, error);
348   else
349     exit(1);
350 }
351 #endif /* HAVE_XDBE_EXTENSION */
352
353
354 Bool InitializeAll(void)
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 XGetWindowAttributes(dpy,win[0],&xgwa);
365 cmap=xgwa.colormap;
366 xswa.backing_store=Always;
367 XChangeWindowAttributes(dpy,win[0],CWBackingStore,&xswa);
368 xgcv.function=GXcopy;
369
370 xgcv.foreground=get_pixel_resource ("background", "Background", dpy, cmap);
371 fgc[32]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
372
373 n=0;
374 if (mono_p)
375         {
376         fgc[0]=fgc[32];
377         xgcv.foreground=get_pixel_resource ("foreground", "Foreground", dpy, cmap);
378         fgc[1]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
379         for (i=0;i<32;i+=2) fgc[i]=fgc[0];
380         for (i=1;i<32;i+=2) fgc[i]=fgc[1];
381         } else
382         for (i=0;i<32;i++)
383         {
384                 color.red=colors[n++]<<8;
385                 color.green=colors[n++]<<8;
386                 color.blue=colors[n++]<<8;
387                 color.flags=DoRed|DoGreen|DoBlue;
388                 XAllocColor(dpy,cmap,&color);
389                 xgcv.foreground=color.pixel;
390                 fgc[i]=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
391         }
392 cgc=XCreateGC(dpy,win[0],GCForeground|GCFunction,&xgcv);
393 XSetGraphicsExposures(dpy,cgc,False);
394
395 if (get_string_resource("random","String")!=NULL && get_string_resource("random","String")[0]!=0) cosilines=False;
396
397 #ifdef HAVE_XDBE_EXTENSION
398 if (get_string_resource("dbuf","String")!=NULL && get_string_resource("dbuf","String")[0]!=0) usedouble=True;
399 if (usedouble)
400         {
401         XdbeQueryExtension(dpy,&n,&i);
402         if (n==0 && i==0)
403                 {
404                 fprintf(stderr,"Double buffer extension not supported!\n");
405                 usedouble=False;
406                 }
407         }
408 if (usedouble)
409   {
410     /* We need to trap an X error when calling XdbeAllocateBackBufferName,
411        because there is no way to know beforehand whether the call will
412        succeed!  This is a totally fucked design, but the man page says:
413
414        ERRORS
415           BadMatch
416                The specified window is not an InputOutput window or
417                its visual does not support DBE.
418
419        With SGI's O2 X server, some visuals support double-buffering (the
420        12-bit pseudocolor visuals) and others yield a BadMatch error, as
421        documented.
422
423        However, it doesn't matter, because using the DBUF extension seems
424        to make it run *slower* instead of faster anyway.
425
426                                                         -- jwz, 1-Jul-98
427      */
428     XSync(dpy, False);
429     old_handler = XSetErrorHandler (BadMatch_ehandler);
430     got_BadMatch = False;
431     win[1] = 0;
432     win[1] = XdbeAllocateBackBufferName(dpy,win[0],XdbeUndefined);
433     XSync(dpy, False);
434     XSetErrorHandler (old_handler);
435     old_handler = 0;
436     XSync(dpy, False);
437     if (got_BadMatch || !win[1])
438       {
439         fprintf(stderr, "%s: visual 0x%x does not support double-buffering.\n",
440                 progname, XVisualIDFromVisual(xgwa.visual));
441         usedouble = False;
442         win[1] = win[0];
443         got_BadMatch = False;
444       }
445   }
446 #endif /* HAVE_XDBE_EXTENSION */
447
448 delay=get_integer_resource("delay","Integer");
449 rspeed=get_float_resource("speed","Float");
450 if (rspeed<0.0001 || rspeed>0.2)
451         {
452         fprintf(stderr,"Speed not in valid range! (0.0001 - 0.2), using 0.1 \n");
453         rspeed=0.1;
454         }
455
456 sizx=xgwa.width;
457 sizy=xgwa.height;
458 midx=sizx>>1;
459 midy=sizy>>1;
460 stateX=0;
461 stateY=0;
462
463 if (!make_rots(rspeed,rspeed))
464         {
465         fprintf(stderr,"Not enough memory for tables!\n");
466         return False;
467         }
468 return True;
469 }
470
471
472 void screenhack(Display *d, Window w)
473 {
474 #ifdef HAVE_XDBE_EXTENSION
475 XdbeSwapInfo xdswp;
476 #endif /* HAVE_XDBE_EXTENSION */
477 int a,b,c,e;
478 float f;
479
480 dpy=d;
481 win[0]=w;
482 if (!InitializeAll()) return;
483
484 #ifdef HAVE_XDBE_EXTENSION
485 if (usedouble)
486         {
487         xdswp.swap_action=XdbeUndefined;
488         xdswp.swap_window=win[0];
489         }
490  else
491 #endif /* HAVE_XDBE_EXTENSION */
492    win[1]=win[0];
493
494 while (0==0)
495         {
496         if (cosilines)
497                 {
498                 c++;
499                 for (a=0;a<8;a++)
500                         {
501                         f=0;
502                         for (b=0;b<3;b++)
503                                 {
504                                 acosinus[a][b]+=cosinus[a][b];
505                                 f+=cosinus[a][b+3]*sin((double)acosinus[a][b]);
506                                 }
507                         coords[a]=(int)f;
508                         }
509                 for (a=0;a<4;a++)
510                         {
511                         XDrawLine(dpy,win[0],(mono_p)?fgc[1]:fgc[((a<<2)+c)&31],midx+ocoords[a<<1],midy+ocoords[(a<<1)+1]
512                         ,midx+coords[a<<1],midy+coords[(a<<1)+1]);
513                         ocoords[a<<1]=coords[a<<1];
514                         ocoords[(a<<1)+1]=coords[(a<<1)+1];
515                         }
516
517                 } else {
518                 for (e=0;e<8;e++)
519                         {
520                         a=Satnum(50);
521                         if (a>=32) a=32;
522                         b=Satnum(32)-16+midx;
523                         c=Satnum(32)-16+midy;
524                         XFillRectangle(dpy,win[0],fgc[a],b,c,2,2);
525                         }
526                 }
527         XFillRectangle(dpy,win[0],fgc[32],midx-2,midy-2,4,4);
528         rotate();
529 #ifdef HAVE_XDBE_EXTENSION
530         if (usedouble) XdbeSwapBuffers(dpy,&xdswp,1);
531 #endif /* HAVE_XDBE_EXTENSION */
532         XSync(dpy,True);
533         if (delay) usleep (delay);
534         }
535 }