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