/* Mennucc:
   how do we use fonts in GL ? simple, we don't !
   http://www.opengl.org/resources/features/fontsurvey/
   shows a lot of examples who need extra libraries;
   this file contains code to use the FTGL library for truetype fonts ;
   this is the only way I know to really support UTF-8 encodings

*/
#include "FTGLPixmapFont.h"

char* fallback_fontfile =DATADIR "/fonts/truetype/freefont/FreeSans.ttf";

extern "C" {
#include <GL/gl.h>
#include "lightspeed.h"
}
#ifdef HAVE_FC
extern "C" {
#include <fontconfig/fontconfig.h>
}
char * find_a_font()
{
  FcChar8* file=NULL;
  char *ret=NULL;
  FcFontSet   *fs=NULL;
  FcPattern   *pat=NULL;
  FcResult    result;
  if (!FcInit ())	{
    g_critical( "Can't init font config library\n");
    return NULL ;
  }
  pat = FcNameParse ((FcChar8 *) "Sans"); 
  //Mennucc : I tried to enforce to have
  //   fontformat: "TrueType"
  // because I thought that that was required for FTGl library;
  // turns out that it is not;  and that the following does not work
  // ( fontconfig is pooorly documented !!)
  const FcChar8 * value  =(FcChar8 *)"TrueType";
  if(FcTrue != FcPatternAddString (pat,  FC_FONTFORMAT , value))  
    g_critical( "Can't use FcPatternAddString\n");
  FcConfigSubstitute (0, pat, FcMatchPattern);
  FcDefaultSubstitute (pat);
  fs = FcFontSort (0, pat, FcTrue, 0, &result);
  if(fs==NULL) {
    FcPattern   *match;
    fs = FcFontSetCreate ();
    match = FcFontMatch (0, pat, &result);
    if (match)
      FcFontSetAdd (fs, match);
  }
  if (pat)
    FcPatternDestroy (pat);
  if (fs){
    int j; for (j = 0; j < fs->nfont && ret == NULL ; j++) {
      if (FcPatternGetString (fs->fonts[j], FC_FILE, 0, &file) 
	  == FcResultMatch) {
	if(file && file[0] && ret == NULL) {
#ifdef DEBUG
	  FcChar8 * ff;
	  FcPatternGetString (fs->fonts[j], FC_FONTFORMAT, 0, &ff);
	  g_message(" font '%s' WILL be  %s ",ff,file);
#endif
	  ret=g_strdup((char *)file);
	}
      }
    }
    FcFontSetDestroy (fs);
  }

  /*  FcFini(); */
  return ret;
}
#endif




void
ogl_draw_string_( const void *data, int message, int size )
{
  static camera *cam=NULL;
  static FTFont* font=NULL;
  char *file=NULL;
  switch (message) {
  case INITIALIZE:
#ifdef HAVE_FC
    if(file==NULL) 
      file=find_a_font();    
#endif
    if(file==NULL) 
      file=fallback_fontfile; 
    if(font==NULL) {
      if (file) { 
	font=new FTGLPixmapFont( file);
	if( font->Error()) {	  
	  fprintf( stderr, "Failed to open font %s", file);
	  return;
	}
      }    else { 
	fprintf( stderr, "Failed to find a font file! ");
	return;
      }}
  
    
    font->Depth(8+size);
    font->CharMap(ft_encoding_unicode);
    break;
  case RESET:
    cam = (camera *)data;
    break;
  default: {
    char *text = (char *)data; 
    g_return_if_fail(text && font && cam);

    int width, height;
    width = cam->width;
    height = cam->height;

    if( !font->FaceSize( 10 + 2* size ))
      {
	g_critical(  "Failed to set size to font");
	return;
      }

    float x1, y1, z1, x2, y2, z2;
    font->BBox( text, x1, y1, z1, x2, y2, z2);
    const int text_width=x2-x1, text_height=y2-y1;
    int x=0, y=0;
    int edge_dx = 1, edge_dy = 1;
    const int pos_code = message;
    /* y coord. of base point */
    switch (pos_code) {
    case POS_BOTTOM_LEFT:
    case POS_BOTTOM_RIGHT:
      y = height / 100;
      edge_dy = 1;
      break;
      
    case POS_TOP_LEFT:
    case POS_TOP_RIGHT:
      y = (99 * height) / 100;
      y -= text_height;
      edge_dy = -1;
      break;
      
    case POS_CENTER:
      y = height / 2;
      y -= text_height / 2;
      edge_dy = -1;
      break;
    }


    /* x coord. of base point */
    switch (pos_code) {
    case POS_TOP_LEFT:
    case POS_BOTTOM_LEFT:
      x = width / 100;
      edge_dx = 1;
      break;
      
    case POS_TOP_RIGHT:
    case POS_BOTTOM_RIGHT:
      x = (width * 99) / 100;
      x -= text_width;
      edge_dx = -1;
      break;
      
    case POS_CENTER:
      x = width / 2;
      x -= text_width / 2;
      edge_dx = 0;
      break;
      
    default:
#ifdef DEBUG
      crash( "ogl_draw_string( ): invalid position code" );
#endif
      return;
    }
    

    //glColor3f( 1.0, 1.0, 1.0);
    
    glPushMatrix();
    
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );
    glOrtho( 0.0, (double)width, 0.0, (double)height, -1.0, 1.0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity( );

    glRasterPos2f(x + edge_dx , y + edge_dy);

    glColor3f( INFODISP_TEXT_FRONT_R, INFODISP_TEXT_FRONT_G, INFODISP_TEXT_FRONT_B );

    font->Render(text);
    glPopMatrix();
  }
  }
}
extern "C" {
  void
  ogl_draw_string( const void *data, int message, int size )
  { return ogl_draw_string_(data,  message,  size );}
}
