1a90e2ddddfa58e468db8736b28c1b7a5f2b1c12
[platform/upstream/gst-plugins-good.git] / gst / goom / ifs.c
1 /*
2  * ifs.c --- modified iterated functions system for goom.
3  */
4
5 /*-
6  * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose and without fee is hereby granted,
10  * provided that the above copyright notice appear in all copies and that
11  * both that copyright notice and this permission notice appear in
12  * supporting documentation.
13  *
14  * This file is provided AS IS with no warranties of any kind.  The author
15  * shall have no liability with respect to the infringement of copyrights,
16  * trade secrets or any patents by this file or any part thereof.  In no
17  * event will the author be liable for any lost revenue or profits or
18  * other special, indirect and consequential damages.
19  *
20  * If this mode is weird and you have an old MetroX server, it is buggy.
21  * There is a free SuSE-enhanced MetroX X server that is fine.
22  *
23  * When shown ifs, Diana Rose (4 years old) said, "It looks like dancing."
24  *
25  * Revision History:
26  * 13-Dec-2003: Added some goom specific stuffs (to make ifs a VisualFX).
27  * 11-Apr-2002: jeko@ios-software.com: Make ifs.c system-indendant. (ifs.h added)
28  * 01-Nov-2000: Allocation checks
29  * 10-May-1997: jwz@jwz.org: turned into a standalone program.
30  *              Made it render into an offscreen bitmap and then copy
31  *              that onto the screen, to reduce flicker.
32  */
33
34 /* #ifdef STANDALONE */
35
36 #include <math.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39
40 #include "goom_config.h"
41
42 #ifdef HAVE_MMX
43 #include "mmx.h"
44 #endif
45
46 #include "goom_graphic.h"
47 #include "ifs.h"
48 #include "goom_tools.h"
49
50 typedef struct _ifsPoint
51 {
52   gint32 x, y;
53 }
54 IFSPoint;
55
56
57 #define MODE_ifs
58
59 #define PROGCLASS "IFS"
60
61 #define HACK_INIT init_ifs
62 #define HACK_DRAW draw_ifs
63
64 #define ifs_opts xlockmore_opts
65
66 #define DEFAULTS "*delay: 20000 \n" \
67 "*ncolors: 100 \n"
68
69 #define SMOOTH_COLORS
70
71 #define LRAND()            ((long) (goom_random(goomInfo->gRandom) & 0x7fffffff))
72 #define NRAND(n)           ((int) (LRAND() % (n)))
73
74 #if RAND_MAX < 0x10000
75 #define MAXRAND (((float)(RAND_MAX<16)+((float)RAND_MAX)+1.0f)/127.0f)
76 #else
77 #define MAXRAND            (2147483648.0/127.0) /* unsigned 1<<31 / 127.0 (cf goom_tools) as a float */
78 #endif
79
80 /*****************************************************/
81
82 typedef float DBL;
83 typedef int F_PT;
84
85 /* typedef float               F_PT; */
86
87 /*****************************************************/
88
89 #define FIX 12
90 #define UNIT   ( 1<<FIX )
91 #define MAX_SIMI  6
92
93 #define MAX_DEPTH_2  10
94 #define MAX_DEPTH_3  6
95 #define MAX_DEPTH_4  4
96 #define MAX_DEPTH_5  2
97
98 /* PREVIOUS VALUE 
99 #define MAX_SIMI  6
100
101  * settings for a PC 120Mhz... *
102 #define MAX_DEPTH_2  10
103 #define MAX_DEPTH_3  6
104 #define MAX_DEPTH_4  4
105 #define MAX_DEPTH_5  3
106 */
107
108 #define DBL_To_F_PT(x)  (F_PT)( (DBL)(UNIT)*(x) )
109
110 typedef struct Similitude_Struct SIMI;
111 typedef struct Fractal_Struct FRACTAL;
112
113 struct Similitude_Struct
114 {
115
116   DBL c_x, c_y;
117   DBL r, r2, A, A2;
118   F_PT Ct, St, Ct2, St2;
119   F_PT Cx, Cy;
120   F_PT R, R2;
121 };
122
123
124 struct Fractal_Struct
125 {
126
127   int Nb_Simi;
128   SIMI Components[5 * MAX_SIMI];
129   int Depth, Col;
130   int Count, Speed;
131   int Width, Height, Lx, Ly;
132   DBL r_mean, dr_mean, dr2_mean;
133   int Cur_Pt, Max_Pt;
134
135   IFSPoint *Buffer1, *Buffer2;
136 };
137
138 typedef struct _IFS_DATA
139 {
140   FRACTAL *Root;
141   FRACTAL *Cur_F;
142
143   /* Used by the Trace recursive method */
144   IFSPoint *Buf;
145   int Cur_Pt;
146   int initalized;
147 } IfsData;
148
149
150 /*****************************************************/
151
152 static DBL
153 Gauss_Rand (PluginInfo * goomInfo, DBL c, DBL A, DBL S)
154 {
155   DBL y;
156
157   y = (DBL) LRAND () / MAXRAND;
158   y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
159   if (NRAND (2))
160     return (c + y);
161   return (c - y);
162 }
163
164 static DBL
165 Half_Gauss_Rand (PluginInfo * goomInfo, DBL c, DBL A, DBL S)
166 {
167   DBL y;
168
169   y = (DBL) LRAND () / MAXRAND;
170   y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
171   return (c + y);
172 }
173
174 static void
175 Random_Simis (PluginInfo * goomInfo, FRACTAL * F, SIMI * Cur, int i)
176 {
177   while (i--) {
178     Cur->c_x = Gauss_Rand (goomInfo, 0.0, .8, 4.0);
179     Cur->c_y = Gauss_Rand (goomInfo, 0.0, .8, 4.0);
180     Cur->r = Gauss_Rand (goomInfo, F->r_mean, F->dr_mean, 3.0);
181     Cur->r2 = Half_Gauss_Rand (goomInfo, 0.0, F->dr2_mean, 2.0);
182     Cur->A = Gauss_Rand (goomInfo, 0.0, 360.0, 4.0) * (M_PI / 180.0);
183     Cur->A2 = Gauss_Rand (goomInfo, 0.0, 360.0, 4.0) * (M_PI / 180.0);
184     Cur++;
185   }
186 }
187
188 static void
189 free_ifs_buffers (FRACTAL * Fractal)
190 {
191   if (Fractal->Buffer1 != NULL) {
192     (void) free ((void *) Fractal->Buffer1);
193     Fractal->Buffer1 = (IFSPoint *) NULL;
194   }
195   if (Fractal->Buffer2 != NULL) {
196     (void) free ((void *) Fractal->Buffer2);
197     Fractal->Buffer2 = (IFSPoint *) NULL;
198   }
199 }
200
201
202 static void
203 free_ifs (FRACTAL * Fractal)
204 {
205   free_ifs_buffers (Fractal);
206 }
207
208 /***************************************************************/
209
210 static void
211 init_ifs (PluginInfo * goomInfo, IfsData * data)
212 {
213   int i;
214   FRACTAL *Fractal;
215   int width = goomInfo->screen.width;
216   int height = goomInfo->screen.height;
217
218   if (data->Root == NULL) {
219     data->Root = (FRACTAL *) malloc (sizeof (FRACTAL));
220     if (data->Root == NULL)
221       return;
222     data->Root->Buffer1 = (IFSPoint *) NULL;
223     data->Root->Buffer2 = (IFSPoint *) NULL;
224   }
225   Fractal = data->Root;
226
227   free_ifs_buffers (Fractal);
228
229   i = (NRAND (4)) + 2;          /* Number of centers */
230   switch (i) {
231     case 3:
232       Fractal->Depth = MAX_DEPTH_3;
233       Fractal->r_mean = .6;
234       Fractal->dr_mean = .4;
235       Fractal->dr2_mean = .3;
236       break;
237
238     case 4:
239       Fractal->Depth = MAX_DEPTH_4;
240       Fractal->r_mean = .5;
241       Fractal->dr_mean = .4;
242       Fractal->dr2_mean = .3;
243       break;
244
245     case 5:
246       Fractal->Depth = MAX_DEPTH_5;
247       Fractal->r_mean = .5;
248       Fractal->dr_mean = .4;
249       Fractal->dr2_mean = .3;
250       break;
251
252     default:
253     case 2:
254       Fractal->Depth = MAX_DEPTH_2;
255       Fractal->r_mean = .7;
256       Fractal->dr_mean = .3;
257       Fractal->dr2_mean = .4;
258       break;
259   }
260   Fractal->Nb_Simi = i;
261   Fractal->Max_Pt = Fractal->Nb_Simi - 1;
262   for (i = 0; i <= Fractal->Depth + 2; ++i)
263     Fractal->Max_Pt *= Fractal->Nb_Simi;
264
265   if ((Fractal->Buffer1 = (IFSPoint *) calloc (Fractal->Max_Pt,
266               sizeof (IFSPoint))) == NULL) {
267     free_ifs (Fractal);
268     return;
269   }
270   if ((Fractal->Buffer2 = (IFSPoint *) calloc (Fractal->Max_Pt,
271               sizeof (IFSPoint))) == NULL) {
272     free_ifs (Fractal);
273     return;
274   }
275
276   Fractal->Speed = 6;
277   Fractal->Width = width;       /* modif by JeKo */
278   Fractal->Height = height;     /* modif by JeKo */
279   Fractal->Cur_Pt = 0;
280   Fractal->Count = 0;
281   Fractal->Lx = (Fractal->Width - 1) / 2;
282   Fractal->Ly = (Fractal->Height - 1) / 2;
283   Fractal->Col = rand () % (width * height);    /* modif by JeKo */
284
285   Random_Simis (goomInfo, Fractal, Fractal->Components, 5 * MAX_SIMI);
286 }
287
288
289 /***************************************************************/
290
291 static inline void
292 Transform (SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
293 {
294   F_PT xx, yy;
295
296   xo = xo - Simi->Cx;
297   xo = (xo * Simi->R) >> FIX;   /* / UNIT; */
298   yo = yo - Simi->Cy;
299   yo = (yo * Simi->R) >> FIX;   /* / UNIT; */
300
301   xx = xo - Simi->Cx;
302   xx = (xx * Simi->R2) >> FIX;  /* / UNIT; */
303   yy = -yo - Simi->Cy;
304   yy = (yy * Simi->R2) >> FIX;  /* / UNIT; */
305
306   *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2)
307       >> FIX /* / UNIT */ ) + Simi->Cx;
308   *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2)
309       >> FIX /* / UNIT */ ) + Simi->Cy;
310 }
311
312 /***************************************************************/
313
314 static void
315 Trace (FRACTAL * F, F_PT xo, F_PT yo, IfsData * data)
316 {
317   F_PT x, y, i;
318   SIMI *Cur;
319
320   Cur = data->Cur_F->Components;
321   for (i = data->Cur_F->Nb_Simi; i; --i, Cur++) {
322     Transform (Cur, xo, yo, &x, &y);
323
324     data->Buf->x = F->Lx + ((x * F->Lx) >> (FIX + 1) /* /(UNIT*2) */ );
325     data->Buf->y = F->Ly - ((y * F->Ly) >> (FIX + 1) /* /(UNIT*2) */ );
326     data->Buf++;
327
328     data->Cur_Pt++;
329
330     if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) {
331       F->Depth--;
332       Trace (F, x, y, data);
333       F->Depth++;
334     }
335   }
336 }
337
338 static void
339 Draw_Fractal (IfsData * data)
340 {
341   FRACTAL *F = data->Root;
342   int i, j;
343   F_PT x, y, xo, yo;
344   SIMI *Cur, *Simi;
345
346   for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
347     Cur->Cx = DBL_To_F_PT (Cur->c_x);
348     Cur->Cy = DBL_To_F_PT (Cur->c_y);
349
350     Cur->Ct = DBL_To_F_PT (cos (Cur->A));
351     Cur->St = DBL_To_F_PT (sin (Cur->A));
352     Cur->Ct2 = DBL_To_F_PT (cos (Cur->A2));
353     Cur->St2 = DBL_To_F_PT (sin (Cur->A2));
354
355     Cur->R = DBL_To_F_PT (Cur->r);
356     Cur->R2 = DBL_To_F_PT (Cur->r2);
357   }
358
359
360   data->Cur_Pt = 0;
361   data->Cur_F = F;
362   data->Buf = F->Buffer2;
363   for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
364     xo = Cur->Cx;
365     yo = Cur->Cy;
366     for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) {
367       if (Simi == Cur)
368         continue;
369       Transform (Simi, xo, yo, &x, &y);
370       Trace (F, x, y, data);
371     }
372   }
373
374   /* Erase previous */
375
376   F->Cur_Pt = data->Cur_Pt;
377   data->Buf = F->Buffer1;
378   F->Buffer1 = F->Buffer2;
379   F->Buffer2 = data->Buf;
380 }
381
382
383 static IFSPoint *
384 draw_ifs (PluginInfo * goomInfo, int *nbpt, IfsData * data)
385 {
386   int i;
387   DBL u, uu, v, vv, u0, u1, u2, u3;
388   SIMI *S, *S1, *S2, *S3, *S4;
389   FRACTAL *F;
390
391   if (data->Root == NULL)
392     return NULL;
393   F = data->Root;
394   if (F->Buffer1 == NULL)
395     return NULL;
396
397   u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0;
398   uu = u * u;
399   v = 1.0 - u;
400   vv = v * v;
401   u0 = vv * v;
402   u1 = 3.0 * vv * u;
403   u2 = 3.0 * v * uu;
404   u3 = u * uu;
405
406   S = F->Components;
407   S1 = S + F->Nb_Simi;
408   S2 = S1 + F->Nb_Simi;
409   S3 = S2 + F->Nb_Simi;
410   S4 = S3 + F->Nb_Simi;
411
412   for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
413     S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x;
414     S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y;
415     S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r;
416     S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2;
417     S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A;
418     S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2;
419   }
420
421   Draw_Fractal (data);
422
423   if (F->Count >= 1000 / F->Speed) {
424     S = F->Components;
425     S1 = S + F->Nb_Simi;
426     S2 = S1 + F->Nb_Simi;
427     S3 = S2 + F->Nb_Simi;
428     S4 = S3 + F->Nb_Simi;
429
430     for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
431       S2->c_x = 2.0 * S4->c_x - S3->c_x;
432       S2->c_y = 2.0 * S4->c_y - S3->c_y;
433       S2->r = 2.0 * S4->r - S3->r;
434       S2->r2 = 2.0 * S4->r2 - S3->r2;
435       S2->A = 2.0 * S4->A - S3->A;
436       S2->A2 = 2.0 * S4->A2 - S3->A2;
437
438       *S1 = *S4;
439     }
440     Random_Simis (goomInfo, F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi);
441
442     Random_Simis (goomInfo, F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi);
443
444     F->Count = 0;
445   } else
446     F->Count++;
447
448   F->Col++;
449
450   (*nbpt) = data->Cur_Pt;
451   return F->Buffer2;
452 }
453
454
455 /***************************************************************/
456
457 static void
458 release_ifs (IfsData * data)
459 {
460   if (data->Root != NULL) {
461     free_ifs (data->Root);
462     (void) free ((void *) data->Root);
463     data->Root = (FRACTAL *) NULL;
464   }
465 }
466
467 #define RAND() goom_random(goomInfo->gRandom)
468
469 static void
470 ifs_update (PluginInfo * goomInfo, Pixel * data, Pixel * back, int increment,
471     IfsData * fx_data)
472 {
473   static unsigned int couleur = 0xc0c0c0c0;
474   static int v[4] = { 2, 4, 3, 2 };
475   static int col[4] = { 2, 4, 3, 2 };
476
477 #define MOD_MER 0
478 #define MOD_FEU 1
479 #define MOD_MERVER 2
480   static int mode = MOD_MERVER;
481   static int justChanged = 0;
482   static int cycle = 0;
483   int cycle10;
484
485   int nbpt = 0;
486   IFSPoint *points;
487   int i;
488
489   unsigned int couleursl = couleur;
490   int width = goomInfo->screen.width;
491   int height = goomInfo->screen.height;
492
493   cycle++;
494   if (cycle >= 80)
495     cycle = 0;
496
497   if (cycle < 40)
498     cycle10 = cycle / 10;
499   else
500     cycle10 = 7 - cycle / 10;
501
502   {
503     unsigned char *tmp = (unsigned char *) &couleursl;
504
505     for (i = 0; i < 4; i++) {
506       *tmp = (*tmp) >> cycle10;
507       tmp++;
508     }
509   }
510
511   points = draw_ifs (goomInfo, &nbpt, fx_data);
512   nbpt--;
513
514 #ifdef HAVE_MMX
515   movd_m2r (couleursl, mm1);
516   punpckldq_r2r (mm1, mm1);
517   for (i = 0; i < nbpt; i += increment) {
518     int x = points[i].x;
519     int y = points[i].y;
520
521     if ((x < width) && (y < height) && (x > 0) && (y > 0)) {
522       int pos = x + (y * width);
523
524       movd_m2r (back[pos], mm0);
525       paddusb_r2r (mm1, mm0);
526       movd_r2m (mm0, data[pos]);
527     }
528   }
529   emms ();     /*__asm__ __volatile__ ("emms");*/
530 #else
531   for (i = 0; i < nbpt; i += increment) {
532     int x = (int) points[i].x & 0x7fffffff;
533     int y = (int) points[i].y & 0x7fffffff;
534
535     if ((x < width) && (y < height)) {
536       int pos = x + (int) (y * width);
537       int tra = 0, i = 0;
538       unsigned char *bra = (unsigned char *) &back[pos];
539       unsigned char *dra = (unsigned char *) &data[pos];
540       unsigned char *cra = (unsigned char *) &couleursl;
541
542       for (; i < 4; i++) {
543         tra = *cra;
544         tra += *bra;
545         if (tra > 255)
546           tra = 255;
547         *dra = tra;
548         ++dra;
549         ++cra;
550         ++bra;
551       }
552     }
553   }
554 #endif /*MMX*/
555       justChanged--;
556
557   col[ALPHA] = couleur >> (ALPHA * 8) & 0xff;
558   col[BLEU] = couleur >> (BLEU * 8) & 0xff;
559   col[VERT] = couleur >> (VERT * 8) & 0xff;
560   col[ROUGE] = couleur >> (ROUGE * 8) & 0xff;
561
562   if (mode == MOD_MER) {
563     col[BLEU] += v[BLEU];
564     if (col[BLEU] > 255) {
565       col[BLEU] = 255;
566       v[BLEU] = -(RAND () % 4) - 1;
567     }
568     if (col[BLEU] < 32) {
569       col[BLEU] = 32;
570       v[BLEU] = (RAND () % 4) + 1;
571     }
572
573     col[VERT] += v[VERT];
574     if (col[VERT] > 200) {
575       col[VERT] = 200;
576       v[VERT] = -(RAND () % 3) - 2;
577     }
578     if (col[VERT] > col[BLEU]) {
579       col[VERT] = col[BLEU];
580       v[VERT] = v[BLEU];
581     }
582     if (col[VERT] < 32) {
583       col[VERT] = 32;
584       v[VERT] = (RAND () % 3) + 2;
585     }
586
587     col[ROUGE] += v[ROUGE];
588     if (col[ROUGE] > 64) {
589       col[ROUGE] = 64;
590       v[ROUGE] = -(RAND () % 4) - 1;
591     }
592     if (col[ROUGE] < 0) {
593       col[ROUGE] = 0;
594       v[ROUGE] = (RAND () % 4) + 1;
595     }
596
597     col[ALPHA] += v[ALPHA];
598     if (col[ALPHA] > 0) {
599       col[ALPHA] = 0;
600       v[ALPHA] = -(RAND () % 4) - 1;
601     }
602     if (col[ALPHA] < 0) {
603       col[ALPHA] = 0;
604       v[ALPHA] = (RAND () % 4) + 1;
605     }
606
607     if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
608             && (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
609             && (RAND () % 20 == 0)) && (justChanged < 0)) {
610       mode = RAND () % 3 ? MOD_FEU : MOD_MERVER;
611       justChanged = 250;
612     }
613   } else if (mode == MOD_MERVER) {
614     col[BLEU] += v[BLEU];
615     if (col[BLEU] > 128) {
616       col[BLEU] = 128;
617       v[BLEU] = -(RAND () % 4) - 1;
618     }
619     if (col[BLEU] < 16) {
620       col[BLEU] = 16;
621       v[BLEU] = (RAND () % 4) + 1;
622     }
623
624     col[VERT] += v[VERT];
625     if (col[VERT] > 200) {
626       col[VERT] = 200;
627       v[VERT] = -(RAND () % 3) - 2;
628     }
629     if (col[VERT] > col[ALPHA]) {
630       col[VERT] = col[ALPHA];
631       v[VERT] = v[ALPHA];
632     }
633     if (col[VERT] < 32) {
634       col[VERT] = 32;
635       v[VERT] = (RAND () % 3) + 2;
636     }
637
638     col[ROUGE] += v[ROUGE];
639     if (col[ROUGE] > 128) {
640       col[ROUGE] = 128;
641       v[ROUGE] = -(RAND () % 4) - 1;
642     }
643     if (col[ROUGE] < 0) {
644       col[ROUGE] = 0;
645       v[ROUGE] = (RAND () % 4) + 1;
646     }
647
648     col[ALPHA] += v[ALPHA];
649     if (col[ALPHA] > 255) {
650       col[ALPHA] = 255;
651       v[ALPHA] = -(RAND () % 4) - 1;
652     }
653     if (col[ALPHA] < 0) {
654       col[ALPHA] = 0;
655       v[ALPHA] = (RAND () % 4) + 1;
656     }
657
658     if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
659             && (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
660             && (RAND () % 20 == 0)) && (justChanged < 0)) {
661       mode = RAND () % 3 ? MOD_FEU : MOD_MER;
662       justChanged = 250;
663     }
664   } else if (mode == MOD_FEU) {
665
666     col[BLEU] += v[BLEU];
667     if (col[BLEU] > 64) {
668       col[BLEU] = 64;
669       v[BLEU] = -(RAND () % 4) - 1;
670     }
671     if (col[BLEU] < 0) {
672       col[BLEU] = 0;
673       v[BLEU] = (RAND () % 4) + 1;
674     }
675
676     col[VERT] += v[VERT];
677     if (col[VERT] > 200) {
678       col[VERT] = 200;
679       v[VERT] = -(RAND () % 3) - 2;
680     }
681     if (col[VERT] > col[ROUGE] + 20) {
682       col[VERT] = col[ROUGE] + 20;
683       v[VERT] = -(RAND () % 3) - 2;
684       v[ROUGE] = (RAND () % 4) + 1;
685       v[BLEU] = (RAND () % 4) + 1;
686     }
687     if (col[VERT] < 0) {
688       col[VERT] = 0;
689       v[VERT] = (RAND () % 3) + 2;
690     }
691
692     col[ROUGE] += v[ROUGE];
693     if (col[ROUGE] > 255) {
694       col[ROUGE] = 255;
695       v[ROUGE] = -(RAND () % 4) - 1;
696     }
697     if (col[ROUGE] > col[VERT] + 40) {
698       col[ROUGE] = col[VERT] + 40;
699       v[ROUGE] = -(RAND () % 4) - 1;
700     }
701     if (col[ROUGE] < 0) {
702       col[ROUGE] = 0;
703       v[ROUGE] = (RAND () % 4) + 1;
704     }
705
706     col[ALPHA] += v[ALPHA];
707     if (col[ALPHA] > 0) {
708       col[ALPHA] = 0;
709       v[ALPHA] = -(RAND () % 4) - 1;
710     }
711     if (col[ALPHA] < 0) {
712       col[ALPHA] = 0;
713       v[ALPHA] = (RAND () % 4) + 1;
714     }
715
716     if (((col[ROUGE] < 64) && (col[VERT] > 32) && (col[VERT] < col[BLEU])
717             && (col[BLEU] > 32)
718             && (RAND () % 20 == 0)) && (justChanged < 0)) {
719       mode = RAND () % 2 ? MOD_MER : MOD_MERVER;
720       justChanged = 250;
721     }
722   }
723
724   couleur = (col[ALPHA] << (ALPHA * 8))
725       | (col[BLEU] << (BLEU * 8))
726       | (col[VERT] << (VERT * 8))
727       | (col[ROUGE] << (ROUGE * 8));
728 }
729
730 /** VISUAL_FX WRAPPER FOR IFS */
731
732 static void
733 ifs_vfx_apply (VisualFX * _this, Pixel * src, Pixel * dest,
734     PluginInfo * goomInfo)
735 {
736
737   IfsData *data = (IfsData *) _this->fx_data;
738
739   if (!data->initalized) {
740     data->initalized = 1;
741     init_ifs (goomInfo, data);
742   }
743   ifs_update (goomInfo, dest, src, goomInfo->update.ifs_incr, data);
744   /*TODO: trouver meilleur soluce pour increment (mettre le code de gestion de l'ifs dans ce fichier: ifs_vfx_apply) */
745 }
746
747 static void
748 ifs_vfx_init (VisualFX * _this, PluginInfo * info)
749 {
750
751   IfsData *data = (IfsData *) malloc (sizeof (IfsData));
752
753   data->Root = (FRACTAL *) NULL;
754   data->initalized = 0;
755   _this->fx_data = data;
756 }
757
758 static void
759 ifs_vfx_free (VisualFX * _this)
760 {
761   IfsData *data = (IfsData *) _this->fx_data;
762
763   release_ifs (data);
764   free (data);
765 }
766
767 VisualFX
768 ifs_visualfx_create (void)
769 {
770   VisualFX vfx;
771
772   vfx.init = ifs_vfx_init;
773   vfx.free = ifs_vfx_free;
774   vfx.apply = ifs_vfx_apply;
775   vfx.fx_data = NULL;
776   vfx.params = NULL;
777   return vfx;
778 }