From http://www.jwz.org/xscreensaver/xscreensaver-5.39.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 #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
126 static int Satnum(int maxi)
127 {
128   return (int)(maxi*frand(1));
129 }
130
131
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
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
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(unsigned int));
219   st->Xrottable=malloc((st->rotsizeX+1)*sizeof(unsigned int));
220   st->Yrotations=malloc((st->midy+2)*sizeof(unsigned int));
221   st->Yrottable=malloc((st->rotsizeY+1)*sizeof(unsigned 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
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 *
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
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
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
517 kumppa_event (Display *dpy, Window window, void *closure, XEvent *event)
518 {
519   return False;
520 }
521
522 static void
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);
535 }
536
537 XSCREENSAVER_MODULE ("Kumppa", kumppa)