configure.ac: Add checks for Flex/Yacc/Bison and other furry animals, for the new...
[platform/upstream/gst-plugins-good.git] / gst / goom / filters.c
1 // --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY ---
2
3 /* filter.c version 0.7
4 * contient les filtres applicable a un buffer
5 * creation : 01/10/2000
6 *  -ajout de sinFilter()
7 *  -ajout de zoomFilter()
8 *  -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs
9 *  -optimisation de sinFilter (utilisant une table de sin)
10 *       -asm
11 *       -optimisation de la procedure de generation du buffer de transformation
12 *               la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
13 */
14
15 /* #define _DEBUG_PIXEL */
16
17 #include <string.h>
18 #include <stdlib.h>
19 #include <math.h>
20 #include <stdio.h>
21 #include <inttypes.h>
22
23 #include "goom_filters.h"
24 #include "goom_graphic.h"
25 #include "goom_tools.h"
26 #include "goom_plugin_info.h"
27 #include "goom_fx.h"
28 #include "v3d.h"
29
30 /* TODO : MOVE THIS AWAY !!! */
31 /* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */
32 static inline void
33 setPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color c)
34 {
35   Pixel i;
36
37   i.channels.b = c.b;
38   i.channels.g = c.v;
39   i.channels.r = c.r;
40   *(buffer + (x + y * goomInfo->screen.width)) = i;
41 }
42
43 static inline void
44 setPixelRGB_ (Pixel * buffer, Uint x, Color c)
45 {
46   buffer[x].channels.r = c.r;
47   buffer[x].channels.g = c.v;
48   buffer[x].channels.b = c.b;
49 }
50
51 static inline void
52 getPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color * c)
53 {
54   Pixel i = *(buffer + (x + y * goomInfo->screen.width));
55
56   c->b = i.channels.b;
57   c->v = i.channels.g;
58   c->r = i.channels.r;
59 }
60
61 static inline void
62 getPixelRGB_ (Pixel * buffer, Uint x, Color * c)
63 {
64   Pixel i = *(buffer + x);
65
66   c->b = i.channels.b;
67   c->v = i.channels.g;
68   c->r = i.channels.r;
69 }
70
71 /* END TODO */
72
73
74 /* DEPRECATED */
75 // retourne x>>s , en testant le signe de x
76 //#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s)))
77 //#define EFFECT_DISTORS 4
78 //#define EFFECT_DISTORS_SL 2
79 //#define INTERLACE_ADD 9
80 //#define INTERLACE_AND 0xf
81 /* END DEPRECATED */
82
83 #define BUFFPOINTNB 16
84 #define BUFFPOINTNBF 16.0f
85 #define BUFFPOINTMASK 0xffff
86
87 #define sqrtperte 16
88 /* faire : a % sqrtperte <=> a & pertemask */
89 #define PERTEMASK 0xf
90 /* faire : a / sqrtperte <=> a >> PERTEDEC */
91 #define PERTEDEC 4
92
93 /* pure c version of the zoom filter */
94 static void c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX,
95     unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio,
96     int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
97
98 /* simple wrapper to give it the same proto than the others */
99 void
100 zoom_filter_c (int sizeX, int sizeY, Pixel * src, Pixel * dest, int *brutS,
101     int *brutD, int buffratio, int precalCoef[16][16])
102 {
103   c_zoom (src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef);
104 }
105
106 static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
107
108
109 typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA
110 {
111
112   PluginParam enabled_bp;
113   PluginParameters params;
114
115   unsigned int *coeffs, *freecoeffs;
116
117   signed int *brutS, *freebrutS;        /* source */
118   signed int *brutD, *freebrutD;        /* dest */
119   signed int *brutT, *freebrutT;        /* temp (en cours de generation) */
120
121   guint32 zoom_width;
122
123   unsigned int prevX, prevY;
124
125   float general_speed;
126   int reverse;                  /* reverse the speed */
127   char theMode;
128   int waveEffect;
129   int hypercosEffect;
130   int vPlaneEffect;
131   int hPlaneEffect;
132   char noisify;
133   int middleX, middleY;
134
135   int mustInitBuffers;
136   int interlace_start;
137
138     /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
139   int buffratio;
140   int *firedec;
141
142     /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
143   int precalCoef[BUFFPOINTNB][BUFFPOINTNB];
144
145     /** calculatePXandPY statics */
146   int wave;
147   int wavesp;
148
149 } ZoomFilterFXWrapperData;
150
151
152
153
154 static inline v2g
155 zoomVector (ZoomFilterFXWrapperData * data, float X, float Y)
156 {
157   v2g vecteur;
158   float vx, vy;
159   float sq_dist = X * X + Y * Y;
160
161   /*    sx = (X < 0.0f) ? -1.0f : 1.0f;
162      sy = (Y < 0.0f) ? -1.0f : 1.0f;
163    */
164   float coefVitesse = (1.0f + data->general_speed) / 50.0f;
165
166   // Effects
167
168   /* Centralized FX */
169
170   switch (data->theMode) {
171     case CRYSTAL_BALL_MODE:
172       coefVitesse -= (sq_dist - 0.3f) / 15.0f;
173       break;
174     case AMULETTE_MODE:
175       coefVitesse += sq_dist * 3.5f;
176       break;
177     case WAVE_MODE:
178       coefVitesse += sin (sq_dist * 20.0f) / 100.0f;
179       break;
180     case SCRUNCH_MODE:
181       coefVitesse += sq_dist / 10.0f;
182       break;
183       //case HYPERCOS1_MODE:
184       break;
185       //case HYPERCOS2_MODE:
186       break;
187       //case YONLY_MODE:
188       break;
189     case SPEEDWAY_MODE:
190       coefVitesse *= 4.0f * Y;
191       break;
192     default:
193       break;
194   }
195
196   if (coefVitesse < -2.01f)
197     coefVitesse = -2.01f;
198   if (coefVitesse > 2.01f)
199     coefVitesse = 2.01f;
200
201   vx = coefVitesse * X;
202   vy = coefVitesse * Y;
203
204   /* Amulette 2 */
205   // vx = X * tan(dist);
206   // vy = Y * tan(dist);
207
208   /* Rotate */
209   //vx = (X+Y)*0.1;
210   //vy = (Y-X)*0.1;
211
212
213   // Effects adds-on
214
215   /* Noise */
216   if (data->noisify) {
217     vx += (((float) random ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
218     vy += (((float) random ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
219   }
220
221   /* Hypercos */
222   if (data->hypercosEffect) {
223     vx += sin (Y * 10.0f) / 120.0f;
224     vy += sin (X * 10.0f) / 120.0f;
225   }
226
227   /* H Plane */
228   if (data->hPlaneEffect)
229     vx += Y * 0.0025f * data->hPlaneEffect;
230
231   /* V Plane */
232   if (data->vPlaneEffect)
233     vy += X * 0.0025f * data->vPlaneEffect;
234
235   /* TODO : Water Mode */
236   //    if (data->waveEffect)
237
238   vecteur.x = vx;
239   vecteur.y = vy;
240
241   return vecteur;
242 }
243
244
245 /*
246  * Makes a stripe of a transform buffer (brutT)
247  *
248  * The transform is (in order) :
249  * Translation (-data->middleX, -data->middleY)
250  * Homothetie (Center : 0,0   Coeff : 2/data->prevX)
251  */
252 static void
253 makeZoomBufferStripe (ZoomFilterFXWrapperData * data, int INTERLACE_INCR)
254 {
255   // Position of the pixel to compute in pixmap coordinates
256   Uint x, y;
257
258   // Where (verticaly) to stop generating the buffer stripe
259   int maxEnd = (data->interlace_start + INTERLACE_INCR);
260
261   // Ratio from pixmap to normalized coordinates
262   float ratio = 2.0f / ((float) data->prevX);
263
264   // Ratio from normalized to virtual pixmap coordinates
265   float inv_ratio = BUFFPOINTNBF / ratio;
266   float min = ratio / BUFFPOINTNBF;
267
268   // Y position of the pixel to compute in normalized coordinates
269   float Y = ((float) (data->interlace_start - data->middleY)) * ratio;
270
271   maxEnd = data->prevY;
272   if (maxEnd > (data->interlace_start + INTERLACE_INCR))
273     maxEnd = (data->interlace_start + INTERLACE_INCR);
274
275   for (y = data->interlace_start;
276       (y < data->prevY) && ((signed int) y < maxEnd); y++) {
277     Uint premul_y_prevX = y * data->prevX * 2;
278     float X = -((float) data->middleX) * ratio;
279
280     for (x = 0; x < data->prevX; x++) {
281       v2g vector = zoomVector (data, X, Y);
282
283       /* Finish and avoid null displacement */
284       if (fabs (vector.x) < min)
285         vector.x = (vector.x < 0.0f) ? -min : min;
286       if (fabs (vector.y) < min)
287         vector.y = (vector.y < 0.0f) ? -min : min;
288
289       data->brutT[premul_y_prevX] =
290           ((int) ((X - vector.x) * inv_ratio) +
291           ((int) (data->middleX * BUFFPOINTNB)));
292       data->brutT[premul_y_prevX + 1] =
293           ((int) ((Y - vector.y) * inv_ratio) +
294           ((int) (data->middleY * BUFFPOINTNB)));
295       premul_y_prevX += 2;
296       X += ratio;
297     }
298     Y += ratio;
299   }
300   data->interlace_start += INTERLACE_INCR;
301   if (y >= data->prevY - 1)
302     data->interlace_start = -1;
303 }
304
305
306 /*
307  * calculer px et py en fonction de x,y,middleX,middleY et theMode
308  * px et py indique la nouvelle position (en sqrtperte ieme de pixel)
309  * (valeur * 16)
310  
311  inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py)
312  {
313      if (data->theMode == WATER_MODE) {
314          int yy;
315          
316          yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10;
317          if (yy < 0)
318              yy = 0;
319          if (yy >= (signed int)goomInfo->screen.height)
320              yy = goomInfo->screen.height - 1;
321          
322          *px = (x << 4) + data->firedec[yy] + (data->wave / 10);
323          *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130);
324          
325          data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
326          if (data->wave < -10)
327              data->wavesp += 2;
328          if (data->wave > 10)
329              data->wavesp -= 2;
330          data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
331          if (data->wavesp > 100)
332              data->wavesp = (data->wavesp * 9) / 10;
333      }
334      else {
335          int     dist = 0, vx9, vy9;
336          int     vx, vy;
337          int     ppx, ppy;
338          int     fvitesse = data->vitesse << 4;
339          
340          if (data->noisify) {
341              x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
342              y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
343          }
344          vx = (x - data->middleX) << 9;
345          vy = (y - data->middleY) << 9;
346          
347          if (data->hPlaneEffect)
348              vx += data->hPlaneEffect * (y - data->middleY);
349          
350          if (data->vPlaneEffect)
351              vy += data->vPlaneEffect * (x - data->middleX);
352          
353          if (data->waveEffect) {
354              fvitesse *=
355              1024 +
356              ShiftRight (goomInfo->sintable
357                          [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6);
358              fvitesse /= 1024;
359          }
360          
361          if (data->hypercosEffect) {
362              vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
363              vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
364          }
365          
366          vx9 = ShiftRight (vx, 9);
367          vy9 = ShiftRight (vy, 9);
368          dist = vx9 * vx9 + vy9 * vy9;
369          
370          switch (data->theMode) {
371              case WAVE_MODE:
372                  fvitesse *=
373                  1024 +
374                  ShiftRight (goomInfo->sintable
375                              [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6);
376                  fvitesse>>=10;
377                  break;
378              case CRYSTAL_BALL_MODE:
379                  fvitesse += (dist >> (10-EFFECT_DISTORS_SL));
380                  break;
381              case AMULETTE_MODE:
382                  fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL));
383                  break;
384              case SCRUNCH_MODE:
385                  fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL));
386                  break;
387              case HYPERCOS1_MODE:
388                  vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
389                  vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
390                  break;
391              case HYPERCOS2_MODE:
392                  vx =
393                  vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0);
394                  vy =
395                      vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0);
396                  fvitesse = 128 << 4;
397                  break;
398              case YONLY_MODE:
399                  fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6);
400                  fvitesse >>= 10;
401                  break;
402              case SPEEDWAY_MODE:
403                  fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL));
404                  break;
405          }
406          
407          if (fvitesse < -3024)
408              fvitesse = -3024;
409          
410          if (vx < 0)                                                                    // pb avec decalage sur nb negatif
411              ppx = -(-(vx * fvitesse) >> 16);
412          // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile)
413          //    * * * * * 9 = nb chiffre virgule de vx) 
414          else
415              ppx = ((vx * fvitesse) >> 16);
416          
417          if (vy < 0)
418              ppy = -(-(vy * fvitesse) >> 16);
419          else
420              ppy = ((vy * fvitesse) >> 16);
421          
422          *px = (data->middleX << 4) + ppx;
423          *py = (data->middleY << 4) + ppy;
424      }
425  }
426  */
427
428
429
430 static void
431 c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX, unsigned int prevY,
432     signed int *brutS, signed int *brutD, int buffratio, int precalCoef[16][16])
433 {
434   int myPos, myPos2;
435   Color couleur;
436
437   unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;
438
439   int bufsize = prevX * prevY * 2;
440   int bufwidth = prevX;
441
442   expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val =
443       expix1[prevX * prevY - prevX].val = 0;
444
445   for (myPos = 0; myPos < bufsize; myPos += 2) {
446     Color col1, col2, col3, col4;
447     int c1, c2, c3, c4, px, py;
448     int pos;
449     int coeffs;
450
451     int brutSmypos = brutS[myPos];
452
453     myPos2 = myPos + 1;
454
455     px = brutSmypos + (((brutD[myPos] -
456                 brutSmypos) * buffratio) >> BUFFPOINTNB);
457     brutSmypos = brutS[myPos2];
458     py = brutSmypos + (((brutD[myPos2] -
459                 brutSmypos) * buffratio) >> BUFFPOINTNB);
460
461     if ((py >= ay) || (px >= ax)) {
462       pos = coeffs = 0;
463     } else {
464       pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
465       /* coef en modulo 15 */
466       coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
467     }
468     getPixelRGB_ (expix1, pos, &col1);
469     getPixelRGB_ (expix1, pos + 1, &col2);
470     getPixelRGB_ (expix1, pos + bufwidth, &col3);
471     getPixelRGB_ (expix1, pos + bufwidth + 1, &col4);
472
473     c1 = coeffs;
474     c2 = (c1 >> 8) & 0xFF;
475     c3 = (c1 >> 16) & 0xFF;
476     c4 = (c1 >> 24) & 0xFF;
477     c1 = c1 & 0xff;
478
479     couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4;
480     if (couleur.r > 5)
481       couleur.r -= 5;
482     couleur.r >>= 8;
483
484     couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4;
485     if (couleur.v > 5)
486       couleur.v -= 5;
487     couleur.v >>= 8;
488
489     couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4;
490     if (couleur.b > 5)
491       couleur.b -= 5;
492     couleur.b >>= 8;
493
494     setPixelRGB_ (expix2, myPos >> 1, couleur);
495   }
496 }
497
498 /** generate the water fx horizontal direction buffer */
499 static void
500 generateTheWaterFXHorizontalDirectionBuffer (PluginInfo * goomInfo,
501     ZoomFilterFXWrapperData * data)
502 {
503
504   int loopv;
505   int decc = goom_irand (goomInfo->gRandom, 8) - 4;
506   int spdc = goom_irand (goomInfo->gRandom, 8) - 4;
507   int accel = goom_irand (goomInfo->gRandom, 8) - 4;
508
509   for (loopv = data->prevY; loopv != 0;) {
510
511     loopv--;
512     data->firedec[loopv] = decc;
513     decc += spdc / 10;
514     spdc +=
515         goom_irand (goomInfo->gRandom, 3) - goom_irand (goomInfo->gRandom, 3);
516
517     if (decc > 4)
518       spdc -= 1;
519     if (decc < -4)
520       spdc += 1;
521
522     if (spdc > 30)
523       spdc = spdc - goom_irand (goomInfo->gRandom, 3) + accel / 10;
524     if (spdc < -30)
525       spdc = spdc + goom_irand (goomInfo->gRandom, 3) + accel / 10;
526
527     if (decc > 8 && spdc > 1)
528       spdc -= goom_irand (goomInfo->gRandom, 3) - 2;
529
530     if (decc < -8 && spdc < -1)
531       spdc += goom_irand (goomInfo->gRandom, 3) + 2;
532
533     if (decc > 8 || decc < -8)
534       decc = decc * 8 / 9;
535
536     accel +=
537         goom_irand (goomInfo->gRandom, 2) - goom_irand (goomInfo->gRandom, 2);
538     if (accel > 20)
539       accel -= 2;
540     if (accel < -20)
541       accel += 2;
542   }
543 }
544
545
546
547 /**
548 * Main work for the dynamic displacement map.
549  * 
550  * Reads data from pix1, write to pix2.
551  *
552  * Useful datas for this FX are stored in ZoomFilterData.
553  * 
554  * If you think that this is a strange function name, let me say that a long time ago,
555  *  there has been a slow version and a gray-level only one. Then came these function,
556  *  fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image.
557  *  So that is why you have this name, for the nostalgy of the first days of goom
558  *  when it was just a tiny program writen in Turbo Pascal on my i486...
559  */
560 void
561 zoomFilterFastRGB (PluginInfo * goomInfo, Pixel * pix1, Pixel * pix2,
562     ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult)
563 {
564   Uint x, y;
565
566   ZoomFilterFXWrapperData *data =
567       (ZoomFilterFXWrapperData *) goomInfo->zoomFilter_fx.fx_data;
568
569   if (!BVAL (data->enabled_bp))
570     return;
571
572     /** changement de taille **/
573   if ((data->prevX != resx) || (data->prevY != resy)) {
574     data->prevX = resx;
575     data->prevY = resy;
576
577     if (data->brutS)
578       free (data->freebrutS);
579     data->brutS = 0;
580     if (data->brutD)
581       free (data->freebrutD);
582     data->brutD = 0;
583     if (data->brutT)
584       free (data->freebrutT);
585     data->brutT = 0;
586
587     data->middleX = resx / 2;
588     data->middleY = resy / 2;
589     data->mustInitBuffers = 1;
590     if (data->firedec)
591       free (data->firedec);
592     data->firedec = 0;
593   }
594
595   if (data->interlace_start != -2)
596     zf = NULL;
597
598     /** changement de config **/
599   if (zf) {
600     data->reverse = zf->reverse;
601     data->general_speed = (float) (zf->vitesse - 128) / 128.0f;
602     if (data->reverse)
603       data->general_speed = -data->general_speed;
604     data->middleX = zf->middleX;
605     data->middleY = zf->middleY;
606     data->theMode = zf->mode;
607     data->hPlaneEffect = zf->hPlaneEffect;
608     data->vPlaneEffect = zf->vPlaneEffect;
609     data->waveEffect = zf->waveEffect;
610     data->hypercosEffect = zf->hypercosEffect;
611     data->noisify = zf->noisify;
612     data->interlace_start = 0;
613   }
614
615
616   if (data->mustInitBuffers) {
617
618     data->mustInitBuffers = 0;
619     data->freebrutS =
620         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
621     data->brutS =
622         (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128);
623
624     data->freebrutD =
625         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
626     data->brutD =
627         (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128);
628
629     data->freebrutT =
630         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
631     data->brutT =
632         (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128);
633
634     data->buffratio = 0;
635
636     data->firedec = (int *) malloc (data->prevY * sizeof (int));
637     generateTheWaterFXHorizontalDirectionBuffer (goomInfo, data);
638
639     data->interlace_start = 0;
640     makeZoomBufferStripe (data, resy);
641
642     /* Copy the data from temp to dest and source */
643     memcpy (data->brutS, data->brutT, resx * resy * 2 * sizeof (int));
644     memcpy (data->brutD, data->brutT, resx * resy * 2 * sizeof (int));
645   }
646
647   /* generation du buffer de trans */
648   if (data->interlace_start == -1) {
649
650     /* sauvegarde de l'etat actuel dans la nouvelle source
651      * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */
652     y = data->prevX * data->prevY * 2;
653     for (x = 0; x < y; x += 2) {
654       int brutSmypos = data->brutS[x];
655       int x2 = x + 1;
656
657       data->brutS[x] =
658           brutSmypos + (((data->brutD[x] -
659                   brutSmypos) * data->buffratio) >> BUFFPOINTNB);
660       brutSmypos = data->brutS[x2];
661       data->brutS[x2] =
662           brutSmypos + (((data->brutD[x2] -
663                   brutSmypos) * data->buffratio) >> BUFFPOINTNB);
664     }
665     data->buffratio = 0;
666   }
667
668   if (data->interlace_start == -1) {
669     signed int *tmp;
670
671     tmp = data->brutD;
672     data->brutD = data->brutT;
673     data->brutT = tmp;
674     tmp = data->freebrutD;
675     data->freebrutD = data->freebrutT;
676     data->freebrutT = tmp;
677     data->interlace_start = -2;
678   }
679
680   if (data->interlace_start >= 0) {
681     /* creation de la nouvelle destination */
682     makeZoomBufferStripe (data, resy / 16);
683   }
684
685   if (switchIncr != 0) {
686     data->buffratio += switchIncr;
687     if (data->buffratio > BUFFPOINTMASK)
688       data->buffratio = BUFFPOINTMASK;
689   }
690
691   if (switchMult != 1.0f) {
692     data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) +
693         (float) data->buffratio * switchMult);
694   }
695
696   data->zoom_width = data->prevX;
697
698   goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2,
699       data->brutS, data->brutD, data->buffratio, data->precalCoef);
700 }
701
702 static void
703 generatePrecalCoef (int precalCoef[16][16])
704 {
705   int coefh, coefv;
706
707   for (coefh = 0; coefh < 16; coefh++) {
708     for (coefv = 0; coefv < 16; coefv++) {
709
710       int i;
711       int diffcoeffh;
712       int diffcoeffv;
713
714       diffcoeffh = sqrtperte - coefh;
715       diffcoeffv = sqrtperte - coefv;
716
717       if (!(coefh || coefv)) {
718         i = 255;
719       } else {
720         int i1, i2, i3, i4;
721
722         i1 = diffcoeffh * diffcoeffv;
723         i2 = coefh * diffcoeffv;
724         i3 = diffcoeffh * coefv;
725         i4 = coefh * coefv;
726
727         // TODO: faire mieux...
728         if (i1)
729           i1--;
730         if (i2)
731           i2--;
732         if (i3)
733           i3--;
734         if (i4)
735           i4--;
736
737         i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24);
738       }
739       precalCoef[coefh][coefv] = i;
740     }
741   }
742 }
743
744 /* VisualFX Wrapper */
745
746 static void
747 zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo * info)
748 {
749   ZoomFilterFXWrapperData *data =
750       (ZoomFilterFXWrapperData *) malloc (sizeof (ZoomFilterFXWrapperData));
751
752   data->coeffs = 0;
753   data->freecoeffs = 0;
754   data->brutS = 0;
755   data->freebrutS = 0;
756   data->brutD = 0;
757   data->freebrutD = 0;
758   data->brutT = 0;
759   data->freebrutT = 0;
760   data->prevX = 0;
761   data->prevY = 0;
762
763   data->mustInitBuffers = 1;
764   data->interlace_start = -2;
765
766   data->general_speed = 0.0f;
767   data->reverse = 0;
768   data->theMode = AMULETTE_MODE;
769   data->waveEffect = 0;
770   data->hypercosEffect = 0;
771   data->vPlaneEffect = 0;
772   data->hPlaneEffect = 0;
773   data->noisify = 2;
774
775     /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
776   data->buffratio = 0;
777   data->firedec = 0;
778
779   data->wave = data->wavesp = 0;
780
781   data->enabled_bp = secure_b_param ("Enabled", 1);
782
783   data->params = plugin_parameters ("Zoom Filter", 1);
784   data->params.params[0] = &data->enabled_bp;
785
786   _this->params = &data->params;
787   _this->fx_data = (void *) data;
788
789     /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
790   generatePrecalCoef (data->precalCoef);
791 }
792
793 static void
794 zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this)
795 {
796   free (_this->fx_data);
797 }
798
799 static void
800 zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel * src,
801     Pixel * dest, PluginInfo * info)
802 {
803 }
804
805 VisualFX
806 zoomFilterVisualFXWrapper_create (void)
807 {
808   VisualFX fx;
809
810   fx.init = zoomFilterVisualFXWrapper_init;
811   fx.free = zoomFilterVisualFXWrapper_free;
812   fx.apply = zoomFilterVisualFXWrapper_apply;
813   return fx;
814 }
815
816
817 /* TODO : MOVE THIS AWAY */
818
819 void
820 pointFilter (PluginInfo * goomInfo, Pixel * pix1, Color c, float t1, float t2,
821     float t3, float t4, Uint cycle)
822 {
823   Uint x = (Uint) ((int) (goomInfo->screen.width / 2)
824       + (int) (t1 * cos ((float) cycle / t3)));
825   Uint y = (Uint) ((int) (goomInfo->screen.height / 2)
826       + (int) (t2 * sin ((float) cycle / t4)));
827
828   if ((x > 1) && (y > 1) && (x < goomInfo->screen.width - 2)
829       && (y < goomInfo->screen.height - 2)) {
830     setPixelRGB (goomInfo, pix1, x + 1, y, c);
831     setPixelRGB (goomInfo, pix1, x, y + 1, c);
832     setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE);
833     setPixelRGB (goomInfo, pix1, x + 2, y + 1, c);
834     setPixelRGB (goomInfo, pix1, x + 1, y + 2, c);
835   }
836 }