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