/*****************************************************************************
 *
 *  Copyright (C) 2003 Cédric Brégardis <cedric.bregardis@free.fr>
 *
 *  This file is part of BRIQUOLO
 *
 *  BRIQUOLO is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  BRIQUOLO 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with BRIQUOLO; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *****************************************************************************/
#include "../I18n.h"
#include "MOGL_PoliceBitmap.h"
#include <fstream>

MOGL_PoliceBitmap::MOGL_PoliceBitmap(): _Nom(0), _Image(NULL), _NbCaractere(0), _Caracteres(NULL)
{
  unsigned int i;
  for(i=0; i<256-32; i++)
  {
        _Correspondance[i]=NULL;
  }
}

bool MOGL_PoliceBitmap::Charger(const char * p_NomFichier)
{
    ifstream file(p_NomFichier, ios::in | ios::binary);
    if (file.fail())
    {
        cerr<<"Error"<<endl;
        return false;
    }
    _NbCaractere = _ReadUnsignedInt(file);
    if (_Caracteres)
    {
        delete [] _Caracteres;
    }
  
    _Caracteres=new MOGL_Struct_Carac[_NbCaractere];

    unsigned int i;
    for(i=0; i<_NbCaractere; i++)
    {
        file.read((char *) &_Caracteres[i].carac, sizeof (_Caracteres[i].carac));
        _Caracteres[i].x1 = _ReadUnsignedInt(file);
        _Caracteres[i].y1 = _ReadUnsignedInt(file);
        _Caracteres[i].x2 = _ReadUnsignedInt(file);
        _Caracteres[i].y2 = _ReadUnsignedInt(file);
    }
    _TailleX = _ReadUnsignedInt(file);
    _TailleY = _ReadUnsignedInt(file);

    _Image=new MOGL_Struct_Couleur[_TailleX*_TailleY];
    MOGL_Struct_Couleur coul;
    for(unsigned int y=0; y<_TailleY; y++)
    {
        for(unsigned int x=0; x<_TailleX; x++)
        {
            unsigned int r, g, b;
            r = _ReadUnsignedInt(file);
            g = _ReadUnsignedInt(file);
            b = _ReadUnsignedInt(file);
            coul.r=r/255.0;
            coul.g=g/255.0;
            coul.b=b/255.0;
            coul.a=(coul.b+coul.g+coul.r)/3;
            coul.r=1;
            coul.g=1;
            coul.b=1;

            _Image[y*_TailleX+x]=coul;
        }
    }

    for(i=0; i<256-32; i++)
    {
        _Correspondance[i]=NULL;
    }
  
    for(i=0; i<_NbCaractere; i++)
    {
        _Correspondance[_Caracteres[i].carac-32]=&_Caracteres[i];
        if (_LargeurMax < _Caracteres[i].x2 - _Caracteres[i].x1)
        {
            _LargeurMax=_Caracteres[i].x2 - _Caracteres[i].x1;
        }
        if (_HauteurMax < _Caracteres[i].y2 - _Caracteres[i].y1)
        {
            _HauteurMax=_Caracteres[i].y2 - _Caracteres[i].y1;
        }
    }

    if (_Nom==0)
    {
        //glDeleteTextures(1,&_Nom);
        glGenTextures(1,&_Nom);
    }
        
    glBindTexture(GL_TEXTURE_2D,_Nom);
    glTexImage2D(GL_TEXTURE_2D,0,4,_TailleX,_TailleY,0,GL_RGBA,GL_FLOAT,_Image);
        
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

    delete [] _Image;
    _NomFichier=p_NomFichier;
    return true;
}

MOGL_PoliceBitmap::~MOGL_PoliceBitmap()
{
  delete [] _Caracteres;
}

void MOGL_PoliceBitmap::Afficher(const string & p_Chaine, int p_X, int p_Y, const MOGL_Struct_Couleur & p_CouleurTexte) const
{
  glEnable(GL_TEXTURE_2D);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_BLEND);
  glDisable(GL_ALPHA_TEST);
  glDisable(GL_DEPTH_TEST);
  glMatrixMode(GL_TEXTURE);
  glLoadIdentity();
  glMatrixMode(GL_MODELVIEW);   

  glBindTexture(GL_TEXTURE_2D,_Nom);
  glColor4f(p_CouleurTexte.r, p_CouleurTexte.g, p_CouleurTexte.b, p_CouleurTexte.a);

  unsigned int taille;
  Uint16 * unicStr = _AllocAndConvertToUCS2(p_Chaine, taille);
  glBegin(GL_QUADS);
  float x=p_X;
  float y=p_Y;
  for(unsigned int i=0; i<taille; i++)
  {
    if (unicStr[i] < 256)
    {
      x=_AfficherCaractere(x, y, unicStr[i]);
    }
  }
  glEnd();
}


void MOGL_PoliceBitmap::Afficher(const string & p_Chaine, int p_X, int p_Y, 
                                 const MOGL_Struct_Couleur & p_CouleurTexte, 
                                 const MOGL_Struct_Couleur & p_CouleurFond) const
{
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_BLEND);
  glDisable(GL_ALPHA_TEST);
  glDisable(GL_DEPTH_TEST);
  glMatrixMode(GL_TEXTURE);
  glLoadIdentity();
  glMatrixMode(GL_MODELVIEW);   

  glBindTexture(GL_TEXTURE_2D,_Nom);

  float x=p_X;
  float y=p_Y;
  unsigned int taille;
  Uint16 * unicStr = _AllocAndConvertToUCS2(p_Chaine, taille);

  for(unsigned int i=0; i<taille; i++)
  {
    if (unicStr[i] < 256)
    {
      glDisable(GL_TEXTURE_2D);
      glColor4f(p_CouleurFond.r, p_CouleurFond.g, p_CouleurFond.b, p_CouleurFond.a);
      glBegin(GL_QUADS);
      _AfficherFondCaractere(x, y, unicStr[i]);
      glEnd();

      glEnable(GL_TEXTURE_2D);
      glColor4f(p_CouleurTexte.r, p_CouleurTexte.g, p_CouleurTexte.b, p_CouleurTexte.a);
      glBegin(GL_QUADS);
      x=_AfficherCaractere(x, y, unicStr[i]);
      glEnd();
    }
  }
}

float MOGL_PoliceBitmap::_AfficherCaractere(float p_X, float p_Y, unsigned char p_Caractere) const
{
  MOGL_Struct_Carac * carac=_Correspondance[p_Caractere-32];
  if (carac)
  {
    unsigned int largeur=carac->x2-carac->x1+1;
    unsigned int hauteur=carac->y2-carac->y1+1;
  
    glTexCoord2f(carac->x1/static_cast<float>(_TailleX), (carac->y1)/static_cast<float>(_TailleY));
    glVertex2f(p_X, p_Y);

    glTexCoord2f(carac->x1/static_cast<float>(_TailleX), (carac->y2+1)/static_cast<float>(_TailleY));
    glVertex2f(p_X, p_Y+hauteur);

    glTexCoord2f((carac->x2+1)/static_cast<float>(_TailleX), (carac->y2+1)/static_cast<float>(_TailleY));
    glVertex2f(p_X+largeur, p_Y+hauteur);

    glTexCoord2f((carac->x2+1)/static_cast<float>(_TailleX), (carac->y1)/static_cast<float>(_TailleY));
    glVertex2f(p_X+largeur, p_Y);
  
    return p_X+largeur;
  }
  else
  {
    return p_X;
  }
  
}

float MOGL_PoliceBitmap::_AfficherFondCaractere(float p_X, float p_Y, unsigned char p_Caractere) const
{
  MOGL_Struct_Carac * carac=_Correspondance[p_Caractere-32];
  if (carac)
  {
    unsigned int largeur=carac->x2-carac->x1+1;
    unsigned int hauteur=carac->y2-carac->y1+1;
  
    glVertex2f(p_X, p_Y);
    glVertex2f(p_X, p_Y+hauteur);
    glVertex2f(p_X+largeur, p_Y+hauteur);
    glVertex2f(p_X+largeur, p_Y);

    return p_X+largeur;
  }
  else
  {
    return p_X;
  }
  
}


unsigned int MOGL_PoliceBitmap::GetTailleXCaractere(Uint16 p_Caractere) const
{
  if (p_Caractere < 256)
  {
    MOGL_Struct_Carac * carac=_Correspondance[p_Caractere-32];
    if (carac)
    {
      return carac->x2-carac->x1+1;
    }
    else
    {
      return 0;
    }
  }
  else
  {
    return 0;
  }
}

unsigned int MOGL_PoliceBitmap::GetTailleYCaractere(Uint16 p_Caractere) const
{
  if (p_Caractere < 256)
  {
    MOGL_Struct_Carac * carac=_Correspondance[p_Caractere-32];
    if (carac)
    {
      return carac->y2-carac->y1+1;
    }
    else
    {
      return 0;
    }
  }
  else
  {
    return 0;
  }
}

bool MOGL_PoliceBitmap::Recharger()
{
  return Charger(_NomFichier.c_str());
}
