/* Goom Project
 * Copyright (C) <2003> iOS-Software
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
// --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY ---

/* filter.c version 0.7
* contient les filtres applicable a un buffer
* creation : 01/10/2000
*  -ajout de sinFilter()
*  -ajout de zoomFilter()
*  -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs
*  -optimisation de sinFilter (utilisant une table de sin)
*	-asm
*	-optimisation de la procedure de generation du buffer de transformation
*		la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
*/

/* #define _DEBUG_PIXEL */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif

#include "goom_filters.h"
#include "goom_graphic.h"
#include "goom_tools.h"
#include "goom_plugin_info.h"
#include "goom_fx.h"
#include "v3d.h"

/* TODO : MOVE THIS AWAY !!! */
/* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */
static inline void
setPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color c)
{
  Pixel i;

  i.channels.b = c.b;
  i.channels.g = c.v;
  i.channels.r = c.r;
  *(buffer + (x + y * goomInfo->screen.width)) = i;
}

static inline void
setPixelRGB_ (Pixel * buffer, Uint x, Color c)
{
  buffer[x].channels.r = c.r;
  buffer[x].channels.g = c.v;
  buffer[x].channels.b = c.b;
}

static inline void
getPixelRGB_ (Pixel * buffer, Uint x, Color * c)
{
  Pixel i = *(buffer + x);

  c->b = i.channels.b;
  c->v = i.channels.g;
  c->r = i.channels.r;
}

/* END TODO */


/* DEPRECATED */
// retourne x>>s , en testant le signe de x
//#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s)))
//#define EFFECT_DISTORS 4
//#define EFFECT_DISTORS_SL 2
//#define INTERLACE_ADD 9
//#define INTERLACE_AND 0xf
/* END DEPRECATED */

#define BUFFPOINTNB 16
#define BUFFPOINTNBF 16.0f
#define BUFFPOINTMASK 0xffff

#define sqrtperte 16
/* faire : a % sqrtperte <=> a & pertemask */
#define PERTEMASK 0xf
/* faire : a / sqrtperte <=> a >> PERTEDEC */
#define PERTEDEC 4

/* pure c version of the zoom filter */
static void c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX,
    unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio,
    int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);

/* simple wrapper to give it the same proto than the others */
void
zoom_filter_c (int sizeX, int sizeY, Pixel * src, Pixel * dest, int *brutS,
    int *brutD, int buffratio, int precalCoef[16][16])
{
  c_zoom (src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef);
}

static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);


typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA
{

  PluginParam enabled_bp;
  PluginParameters params;

  unsigned int *coeffs, *freecoeffs;

  signed int *brutS, *freebrutS;        /* source */
  signed int *brutD, *freebrutD;        /* dest */
  signed int *brutT, *freebrutT;        /* temp (en cours de generation) */

  guint32 zoom_width;

  unsigned int prevX, prevY;

  float general_speed;
  int reverse;                  /* reverse the speed */
  char theMode;
  int waveEffect;
  int hypercosEffect;
  int vPlaneEffect;
  int hPlaneEffect;
  char noisify;
  int middleX, middleY;

  int mustInitBuffers;
  int interlace_start;

    /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
  int buffratio;
  int *firedec;

    /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
  int precalCoef[BUFFPOINTNB][BUFFPOINTNB];

    /** calculatePXandPY statics */
  int wave;
  int wavesp;

} ZoomFilterFXWrapperData;




static inline void
zoomVector (v2g * vecteur, ZoomFilterFXWrapperData * data, float X, float Y)
{
  float vx, vy;
  float sq_dist = X * X + Y * Y;

  /*    sx = (X < 0.0f) ? -1.0f : 1.0f;
     sy = (Y < 0.0f) ? -1.0f : 1.0f;
   */
  float coefVitesse = (1.0f + data->general_speed) / 50.0f;

  // Effects

  /* Centralized FX */

  switch (data->theMode) {
    case CRYSTAL_BALL_MODE:
      coefVitesse -= (sq_dist - 0.3f) / 15.0f;
      break;
    case AMULETTE_MODE:
      coefVitesse += sq_dist * 3.5f;
      break;
    case WAVE_MODE:
      coefVitesse += sin (sq_dist * 20.0f) / 100.0f;
      break;
    case SCRUNCH_MODE:
      coefVitesse += sq_dist / 10.0f;
      break;
      //case HYPERCOS1_MODE:
      break;
      //case HYPERCOS2_MODE:
      break;
      //case YONLY_MODE:
      break;
    case SPEEDWAY_MODE:
      coefVitesse *= 4.0f * Y;
      break;
    default:
      break;
  }

  if (coefVitesse < -2.01f)
    coefVitesse = -2.01f;
  if (coefVitesse > 2.01f)
    coefVitesse = 2.01f;

  vx = coefVitesse * X;
  vy = coefVitesse * Y;

  /* Amulette 2 */
  // vx = X * tan(dist);
  // vy = Y * tan(dist);

  /* Rotate */
  //vx = (X+Y)*0.1;
  //vy = (Y-X)*0.1;


  // Effects adds-on

  /* Noise */
  if (data->noisify) {
    vx += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
    vy += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
  }

  /* Hypercos */
  if (data->hypercosEffect) {
    vx += sin (Y * 10.0f) / 120.0f;
    vy += sin (X * 10.0f) / 120.0f;
  }

  /* H Plane */
  if (data->hPlaneEffect)
    vx += Y * 0.0025f * data->hPlaneEffect;

  /* V Plane */
  if (data->vPlaneEffect)
    vy += X * 0.0025f * data->vPlaneEffect;

  /* TODO : Water Mode */
  //    if (data->waveEffect)

  vecteur->x = vx;
  vecteur->y = vy;
}


/*
 * Makes a stripe of a transform buffer (brutT)
 *
 * The transform is (in order) :
 * Translation (-data->middleX, -data->middleY)
 * Homothetie (Center : 0,0   Coeff : 2/data->prevX)
 */
static void
makeZoomBufferStripe (ZoomFilterFXWrapperData * data, int INTERLACE_INCR)
{
  // Position of the pixel to compute in pixmap coordinates
  Uint x, y;

  // Where (verticaly) to stop generating the buffer stripe
  int maxEnd;

  // Ratio from pixmap to normalized coordinates
  float ratio = 2.0f / ((float) data->prevX);

  // Ratio from normalized to virtual pixmap coordinates
  float inv_ratio = BUFFPOINTNBF / ratio;
  float min = ratio / BUFFPOINTNBF;

  // Y position of the pixel to compute in normalized coordinates
  float Y = ((float) (data->interlace_start - data->middleY)) * ratio;

  maxEnd = data->prevY;
  if (maxEnd > (data->interlace_start + INTERLACE_INCR))
    maxEnd = (data->interlace_start + INTERLACE_INCR);

  for (y = data->interlace_start;
      (y < data->prevY) && ((signed int) y < maxEnd); y++) {
    Uint premul_y_prevX = y * data->prevX * 2;
    float X = -((float) data->middleX) * ratio;

    for (x = 0; x < data->prevX; x++) {
      v2g vector;

      zoomVector (&vector, data, X, Y);

      /* Finish and avoid null displacement */
      if (fabs (vector.x) < min)
        vector.x = (vector.x < 0.0f) ? -min : min;
      if (fabs (vector.y) < min)
        vector.y = (vector.y < 0.0f) ? -min : min;

      data->brutT[premul_y_prevX] =
          ((int) ((X - vector.x) * inv_ratio) +
          ((int) (data->middleX * BUFFPOINTNB)));
      data->brutT[premul_y_prevX + 1] =
          ((int) ((Y - vector.y) * inv_ratio) +
          ((int) (data->middleY * BUFFPOINTNB)));
      premul_y_prevX += 2;
      X += ratio;
    }
    Y += ratio;
  }
  data->interlace_start += INTERLACE_INCR;
  if (y >= data->prevY - 1)
    data->interlace_start = -1;
}


/*
 * calculer px et py en fonction de x,y,middleX,middleY et theMode
 * px et py indique la nouvelle position (en sqrtperte ieme de pixel)
 * (valeur * 16)
 
 inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py)
 {
     if (data->theMode == WATER_MODE) {
         int yy;
         
         yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10;
         if (yy < 0)
             yy = 0;
         if (yy >= (signed int)goomInfo->screen.height)
             yy = goomInfo->screen.height - 1;
         
         *px = (x << 4) + data->firedec[yy] + (data->wave / 10);
         *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130);
         
         data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
         if (data->wave < -10)
             data->wavesp += 2;
         if (data->wave > 10)
             data->wavesp -= 2;
         data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
         if (data->wavesp > 100)
             data->wavesp = (data->wavesp * 9) / 10;
     }
     else {
         int     dist = 0, vx9, vy9;
         int     vx, vy;
         int     ppx, ppy;
         int     fvitesse = data->vitesse << 4;
         
         if (data->noisify) {
             x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
             y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
         }
         vx = (x - data->middleX) << 9;
         vy = (y - data->middleY) << 9;
         
         if (data->hPlaneEffect)
             vx += data->hPlaneEffect * (y - data->middleY);
         
         if (data->vPlaneEffect)
             vy += data->vPlaneEffect * (x - data->middleX);
         
         if (data->waveEffect) {
             fvitesse *=
             1024 +
             ShiftRight (goomInfo->sintable
                         [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6);
             fvitesse /= 1024;
         }
         
         if (data->hypercosEffect) {
             vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
             vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
         }
         
         vx9 = ShiftRight (vx, 9);
         vy9 = ShiftRight (vy, 9);
         dist = vx9 * vx9 + vy9 * vy9;
         
         switch (data->theMode) {
             case WAVE_MODE:
                 fvitesse *=
                 1024 +
                 ShiftRight (goomInfo->sintable
                             [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6);
                 fvitesse>>=10;
                 break;
             case CRYSTAL_BALL_MODE:
                 fvitesse += (dist >> (10-EFFECT_DISTORS_SL));
                 break;
             case AMULETTE_MODE:
                 fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL));
                 break;
             case SCRUNCH_MODE:
                 fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL));
                 break;
             case HYPERCOS1_MODE:
                 vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
                 vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
                 break;
             case HYPERCOS2_MODE:
                 vx =
                 vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0);
                 vy =
                     vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0);
                 fvitesse = 128 << 4;
                 break;
             case YONLY_MODE:
                 fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6);
                 fvitesse >>= 10;
                 break;
             case SPEEDWAY_MODE:
                 fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL));
                 break;
         }
         
         if (fvitesse < -3024)
             fvitesse = -3024;
         
         if (vx < 0)									// pb avec decalage sur nb negatif
             ppx = -(-(vx * fvitesse) >> 16);
         // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile)
         //    * * * * * 9 = nb chiffre virgule de vx) 
         else
             ppx = ((vx * fvitesse) >> 16);
         
         if (vy < 0)
             ppy = -(-(vy * fvitesse) >> 16);
         else
             ppy = ((vy * fvitesse) >> 16);
         
         *px = (data->middleX << 4) + ppx;
         *py = (data->middleY << 4) + ppy;
     }
 }
 */



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])
{
  int myPos, myPos2;
  Color couleur;

  unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;

  int bufsize = prevX * prevY * 2;
  int bufwidth = prevX;

  expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val =
      expix1[prevX * prevY - prevX].val = 0;

  for (myPos = 0; myPos < bufsize; myPos += 2) {
    Color col1, col2, col3, col4;
    int c1, c2, c3, c4, px, py;
    int pos;
    int coeffs;

    int brutSmypos = brutS[myPos];

    myPos2 = myPos + 1;

    px = brutSmypos + (((brutD[myPos] -
                brutSmypos) * buffratio) >> BUFFPOINTNB);
    brutSmypos = brutS[myPos2];
    py = brutSmypos + (((brutD[myPos2] -
                brutSmypos) * buffratio) >> BUFFPOINTNB);

    if ((py >= ay) || (px >= ax)) {
      pos = coeffs = 0;
    } else {
      pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
      /* coef en modulo 15 */
      coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
    }
    getPixelRGB_ (expix1, pos, &col1);
    getPixelRGB_ (expix1, pos + 1, &col2);
    getPixelRGB_ (expix1, pos + bufwidth, &col3);
    getPixelRGB_ (expix1, pos + bufwidth + 1, &col4);

    c1 = coeffs;
    c2 = (c1 >> 8) & 0xFF;
    c3 = (c1 >> 16) & 0xFF;
    c4 = (c1 >> 24) & 0xFF;
    c1 = c1 & 0xff;

    couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4;
    if (couleur.r > 5)
      couleur.r -= 5;
    couleur.r >>= 8;

    couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4;
    if (couleur.v > 5)
      couleur.v -= 5;
    couleur.v >>= 8;

    couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4;
    if (couleur.b > 5)
      couleur.b -= 5;
    couleur.b >>= 8;

    setPixelRGB_ (expix2, myPos >> 1, couleur);
  }
}

/** generate the water fx horizontal direction buffer */
static void
generateTheWaterFXHorizontalDirectionBuffer (PluginInfo * goomInfo,
    ZoomFilterFXWrapperData * data)
{

  int loopv;
  int decc = goom_irand (goomInfo->gRandom, 8) - 4;
  int spdc = goom_irand (goomInfo->gRandom, 8) - 4;
  int accel = goom_irand (goomInfo->gRandom, 8) - 4;

  for (loopv = data->prevY; loopv != 0;) {

    loopv--;
    data->firedec[loopv] = decc;
    decc += spdc / 10;
    spdc +=
        goom_irand (goomInfo->gRandom, 3) - goom_irand (goomInfo->gRandom, 3);

    if (decc > 4)
      spdc -= 1;
    if (decc < -4)
      spdc += 1;

    if (spdc > 30)
      spdc = spdc - goom_irand (goomInfo->gRandom, 3) + accel / 10;
    if (spdc < -30)
      spdc = spdc + goom_irand (goomInfo->gRandom, 3) + accel / 10;

    if (decc > 8 && spdc > 1)
      spdc -= goom_irand (goomInfo->gRandom, 3) - 2;

    if (decc < -8 && spdc < -1)
      spdc += goom_irand (goomInfo->gRandom, 3) + 2;

    if (decc > 8 || decc < -8)
      decc = decc * 8 / 9;

    accel +=
        goom_irand (goomInfo->gRandom, 2) - goom_irand (goomInfo->gRandom, 2);
    if (accel > 20)
      accel -= 2;
    if (accel < -20)
      accel += 2;
  }
}



/**
* Main work for the dynamic displacement map.
 * 
 * Reads data from pix1, write to pix2.
 *
 * Useful datas for this FX are stored in ZoomFilterData.
 * 
 * If you think that this is a strange function name, let me say that a long time ago,
 *  there has been a slow version and a gray-level only one. Then came these function,
 *  fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image.
 *  So that is why you have this name, for the nostalgy of the first days of goom
 *  when it was just a tiny program writen in Turbo Pascal on my i486...
 */
void
zoomFilterFastRGB (PluginInfo * goomInfo, Pixel * pix1, Pixel * pix2,
    ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult)
{
  Uint x, y;

  ZoomFilterFXWrapperData *data =
      (ZoomFilterFXWrapperData *) goomInfo->zoomFilter_fx.fx_data;

  if (!BVAL (data->enabled_bp))
    return;

    /** changement de taille **/
  if ((data->prevX != resx) || (data->prevY != resy)) {
    data->prevX = resx;
    data->prevY = resy;

    if (data->brutS)
      free (data->freebrutS);
    data->brutS = 0;
    if (data->brutD)
      free (data->freebrutD);
    data->brutD = 0;
    if (data->brutT)
      free (data->freebrutT);
    data->brutT = 0;

    data->middleX = resx / 2;
    data->middleY = resy / 2;
    data->mustInitBuffers = 1;
    if (data->firedec)
      free (data->firedec);
    data->firedec = 0;
  }

  if (data->interlace_start != -2)
    zf = NULL;

    /** changement de config **/
  if (zf) {
    data->reverse = zf->reverse;
    data->general_speed = (float) (zf->vitesse - 128) / 128.0f;
    if (data->reverse)
      data->general_speed = -data->general_speed;
    data->middleX = zf->middleX;
    data->middleY = zf->middleY;
    data->theMode = zf->mode;
    data->hPlaneEffect = zf->hPlaneEffect;
    data->vPlaneEffect = zf->vPlaneEffect;
    data->waveEffect = zf->waveEffect;
    data->hypercosEffect = zf->hypercosEffect;
    data->noisify = zf->noisify;
    data->interlace_start = 0;
  }


  if (data->mustInitBuffers) {

    data->mustInitBuffers = 0;
    data->freebrutS =
        (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
    data->brutS =
        (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128);

    data->freebrutD =
        (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
    data->brutD =
        (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128);

    data->freebrutT =
        (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
    data->brutT =
        (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128);

    data->buffratio = 0;

    data->firedec = (int *) malloc (data->prevY * sizeof (int));
    generateTheWaterFXHorizontalDirectionBuffer (goomInfo, data);

    data->interlace_start = 0;
    makeZoomBufferStripe (data, resy);

    /* Copy the data from temp to dest and source */
    memcpy (data->brutS, data->brutT, resx * resy * 2 * sizeof (int));
    memcpy (data->brutD, data->brutT, resx * resy * 2 * sizeof (int));
  }

  /* generation du buffer de trans */
  if (data->interlace_start == -1) {

    /* sauvegarde de l'etat actuel dans la nouvelle source
     * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */
    y = data->prevX * data->prevY * 2;
    for (x = 0; x < y; x += 2) {
      int brutSmypos = data->brutS[x];
      int x2 = x + 1;

      data->brutS[x] =
          brutSmypos + (((data->brutD[x] -
                  brutSmypos) * data->buffratio) >> BUFFPOINTNB);
      brutSmypos = data->brutS[x2];
      data->brutS[x2] =
          brutSmypos + (((data->brutD[x2] -
                  brutSmypos) * data->buffratio) >> BUFFPOINTNB);
    }
    data->buffratio = 0;
  }

  if (data->interlace_start == -1) {
    signed int *tmp;

    tmp = data->brutD;
    data->brutD = data->brutT;
    data->brutT = tmp;
    tmp = data->freebrutD;
    data->freebrutD = data->freebrutT;
    data->freebrutT = tmp;
    data->interlace_start = -2;
  }

  if (data->interlace_start >= 0) {
    /* creation de la nouvelle destination */
    makeZoomBufferStripe (data, resy / 16);
  }

  if (switchIncr != 0) {
    data->buffratio += switchIncr;
    if (data->buffratio > BUFFPOINTMASK)
      data->buffratio = BUFFPOINTMASK;
  }

  if (switchMult != 1.0f) {
    data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) +
        (float) data->buffratio * switchMult);
  }

  data->zoom_width = data->prevX;

  goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2,
      data->brutS, data->brutD, data->buffratio, data->precalCoef);
}

static void
generatePrecalCoef (int precalCoef[16][16])
{
  int coefh, coefv;

  for (coefh = 0; coefh < 16; coefh++) {
    for (coefv = 0; coefv < 16; coefv++) {

      int i;
      int diffcoeffh;
      int diffcoeffv;

      diffcoeffh = sqrtperte - coefh;
      diffcoeffv = sqrtperte - coefv;

      if (!(coefh || coefv)) {
        i = 255;
      } else {
        Uint i1, i2, i3, i4;

        i1 = diffcoeffh * diffcoeffv;
        i2 = coefh * diffcoeffv;
        i3 = diffcoeffh * coefv;
        i4 = coefh * coefv;

        // TODO: faire mieux...
        if (i1)
          i1--;
        if (i2)
          i2--;
        if (i3)
          i3--;
        if (i4)
          i4--;

        i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24);
      }
      precalCoef[coefh][coefv] = i;
    }
  }
}

/* VisualFX Wrapper */

static void
zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo * info)
{
  ZoomFilterFXWrapperData *data =
      (ZoomFilterFXWrapperData *) malloc (sizeof (ZoomFilterFXWrapperData));

  data->coeffs = 0;
  data->freecoeffs = 0;
  data->brutS = 0;
  data->freebrutS = 0;
  data->brutD = 0;
  data->freebrutD = 0;
  data->brutT = 0;
  data->freebrutT = 0;
  data->prevX = 0;
  data->prevY = 0;

  data->mustInitBuffers = 1;
  data->interlace_start = -2;

  data->general_speed = 0.0f;
  data->reverse = 0;
  data->theMode = AMULETTE_MODE;
  data->waveEffect = 0;
  data->hypercosEffect = 0;
  data->vPlaneEffect = 0;
  data->hPlaneEffect = 0;
  data->noisify = 2;

    /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
  data->buffratio = 0;
  data->firedec = 0;

  data->wave = data->wavesp = 0;

  secure_b_param (&data->enabled_bp, "Enabled", 1);

  plugin_parameters (&data->params, "Zoom Filter", 1);
  data->params.params[0] = &data->enabled_bp;

  _this->params = &data->params;
  _this->fx_data = (void *) data;

    /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
  generatePrecalCoef (data->precalCoef);
}

static void
zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this)
{
  ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData *) _this->fx_data;

  if (data->freebrutT)
    free (data->freebrutT);
  if (data->freebrutS)
    free (data->freebrutS);
  if (data->freebrutD)
    free (data->freebrutD);
  if (data->firedec)
    free (data->firedec);

  goom_plugin_parameters_free (_this->params);

  free (_this->fx_data);
}

static void
zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel * src,
    Pixel * dest, PluginInfo * info)
{
}

void
zoomFilterVisualFXWrapper_create (VisualFX * fx)
{
  fx->init = zoomFilterVisualFXWrapper_init;
  fx->free = zoomFilterVisualFXWrapper_free;
  fx->apply = zoomFilterVisualFXWrapper_apply;
  fx->params = NULL;
  fx->fx_data = NULL;
}


/* TODO : MOVE THIS AWAY */

void
pointFilter (PluginInfo * goomInfo, Pixel * pix1, Color c, float t1, float t2,
    float t3, float t4, Uint cycle)
{
  Uint x = (Uint) ((int) (goomInfo->screen.width / 2)
      + (int) (t1 * cos ((float) cycle / t3)));
  Uint y = (Uint) ((int) (goomInfo->screen.height / 2)
      + (int) (t2 * sin ((float) cycle / t4)));

  if ((x > 1) && (y > 1) && (x < goomInfo->screen.width - 2)
      && (y < goomInfo->screen.height - 2)) {
    setPixelRGB (goomInfo, pix1, x + 1, y, c);
    setPixelRGB (goomInfo, pix1, x, y + 1, c);
    setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE);
    setPixelRGB (goomInfo, pix1, x + 2, y + 1, c);
    setPixelRGB (goomInfo, pix1, x + 1, y + 2, c);
  }
}
