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