/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2005)
  
	Adresse mèl :
	BILLARD, non joignable par mèl ;
	CALISTE, damien P caliste AT cea P fr.

	Ce logiciel est un programme informatique servant à visualiser des
	structures atomiques dans un rendu pseudo-3D. 

	Ce logiciel est régi par la licence CeCILL soumise au droit français et
	respectant les principes de diffusion des logiciels libres. Vous pouvez
	utiliser, modifier et/ou redistribuer ce programme sous les conditions
	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
	sur le site "http://www.cecill.info".

	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
	pris connaissance de la licence CeCILL, et que vous en avez accepté les
	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
*/

/*   LICENCE SUM UP
	Copyright CEA, contributors : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2005)

	E-mail address:
	BILLARD, not reachable any more ;
	CALISTE, damien P caliste AT cea P fr.

	This software is a computer program whose purpose is to visualize atomic
	configurations in 3D.

	This software is governed by the CeCILL  license under French law and
	abiding by the rules of distribution of free software.  You can  use, 
	modify and/ or redistribute the software under the terms of the CeCILL
	license as circulated by CEA, CNRS and INRIA at the following URL
	"http://www.cecill.info". 

	The fact that you are presently reading this means that you have had
	knowledge of the CeCILL license and that you accept its terms. You can
	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
*/
#include "text.h"

#include <string.h>

#include <visu_tools.h>
#include <OSOpenGL/visu_openGL.h>

#ifdef HAVE_FTGL
#include <FTGL/ftgl.h>
#endif

/**
 * SECTION:text
 * @short_description: Enables capabilities to write some text on rendering screen.
 * 
 * <para>For the moment, this module is very basic and the only fonts
 * available is the helvetica 12 one. This module is currently broken
 * under Windows.</para>
 */

static GLuint BASE;  /* for the font display list */
static GLuint SMALL; /* for the small font display list */
static gboolean textListHaveBeenBuilt = FALSE;

#ifdef HAVE_FTGL
static FTGLfont *font = NULL;
#endif
static float fontSize = 32.f; /* only used in the case of FTGL. */

static void _putGlText(const gchar *text, VisuGlTextSize size)
{
  g_return_if_fail(textListHaveBeenBuilt);

  glPushAttrib(GL_LIST_BIT);
  if (size == VISU_GL_TEXT_SMALL && SMALL > 0)
    glListBase(SMALL);
  else
    glListBase(BASE);
  glCallLists((int)strlen(text), GL_UNSIGNED_BYTE, (GLubyte *)text);
  glPopAttrib();
}
static VisuGlTextFunc renderText = _putGlText;

/**
 * visu_gl_text_putTextWithFTGL:
 * @text: the text to write.
 * @size: the size.
 *
 * A #VisuGlTextFunc routine using FTGL to render text with Pixmap
 * lists, see visu_gl_text_setFunc().
 *
 * Since: 3.7
 **/
void visu_gl_text_putTextWithFTGL(const gchar *text, VisuGlTextSize size)
{
  g_return_if_fail(textListHaveBeenBuilt);

#ifdef HAVE_FTGL
  if (size == VISU_GL_TEXT_NORMAL)
    ftglSetFontFaceSize(font, fontSize, fontSize);
  else
    ftglSetFontFaceSize(font, fontSize * 0.75f, fontSize * 0.75f);
  /* glGetFloatv(GL_CURRENT_COLOR, color); */
  /* glPixelTransferf(GL_RED_BIAS, 255.f * color[0]); */
  /* glPixelTransferf(GL_GREEN_BIAS, 255.f * color[1]); */
  /* glPixelTransferf(GL_BLUE_BIAS, 255.f * color[2]); */
  ftglRenderFont(font, text, FTGL_RENDER_ALL);
  /* glPixelTransferf(GL_RED_BIAS, 0.f); */
  /* glPixelTransferf(GL_GREEN_BIAS, 0.f); */
  /* glPixelTransferf(GL_BLUE_BIAS, 0.f); */
#else
  g_warning("FTGL backend not compiled, unable to write '%s' at size %d.", text, size);
#endif
}

/**
 * visu_gl_text_setFunc:
 * @func: (scope call) (allow-none): a #VisuGlTextFunc function
 *
 * Set the function to render text at the raster position.
 *
 * Since: 3.7
 *
 * Returns: TRUE if the function is indeed changed.
 **/
gboolean visu_gl_text_setFunc(VisuGlTextFunc func)
{
  if (func == renderText)
    return FALSE;

  renderText = (func)?func:_putGlText;
  return TRUE;
}
/**
 * visu_gl_text_setFontSize:
 * @size: a new size.
 *
 * Change the normal font size used by V_Sim (see
 * #VISU_GL_TEXT_NORMAL). The small font is scaled accordingly. This is working only
 * with the FTGL backend.
 *
 * Since: 3.7
 *
 * Returns: TRUE if font size is indeed changed.
 **/
gboolean visu_gl_text_setFontSize(float size)
{
  if (size == fontSize)
    return FALSE;

  fontSize = CLAMP(size, 12.f, 999.f);
  return TRUE;
}

/**
 * visu_gl_text_drawChars:
 * @s: a string.
 * @size: the size of the text to render.
 *
 * Draw the given string on the current raster position with default
 * font.
 */
void visu_gl_text_drawChars(const gchar *s, VisuGlTextSize size)
{
  gsize nread, nwritten;
  GError *error;
  gchar *text;

  g_return_if_fail(s);

  DBG_fprintf(stderr, "OpenGL Text: put text '%s'.\n", s);
  error = (GError*)0;
  text = g_convert_with_fallback(s, -1, "iso-8859-1", "utf-8", "<?>",
                                 &nread, &nwritten, &error);
  if (text)
    {
      renderText(text, size);
      g_free(text);
    }
  else
    {
      g_warning("%s", error->message);
      g_error_free(error);
    }
}
/**
 * visu_gl_text_initFontList:
 *
 * Initialise the font drawing with default font (depending on system).
 * It must be called before visu_gl_text_drawChars() and not in a glNewList().
 * Can be called several times, fonts are initialized once only. Use
 * visu_gl_text_rebuildFontList() to force to build a new font list.
 */
void visu_gl_text_initFontList()
{
  if (textListHaveBeenBuilt)
    return;

  BASE  = visu_gl_initFontList(18);
  SMALL = visu_gl_initFontList(14);
  textListHaveBeenBuilt = (BASE > 0);
  DBG_fprintf(stderr, "OpenGL Text: creating font list: %d %d.\n", BASE, SMALL);
  g_return_if_fail(BASE > 0 && SMALL > 0);

#ifdef HAVE_FTGL
  font = ftglCreatePixmapFont("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf");
#endif
}
/**
 * visu_gl_text_rebuildFontList:
 *
 * Force to buid a new font list (for example new context has changed.
 */
void visu_gl_text_rebuildFontList()
{
  DBG_fprintf(stderr, "OpenGL Text: rebuilding font list.\n");
  visu_gl_text_initFontList();
}
/**
 * visu_gl_text_onNewContext:
 *
 * Set the flag for text list build to FALSE. It will force to rebuild
 * the text lists at next call of visu_gl_text_initFontList().
 *
 * Since: 3.6
 */
void visu_gl_text_onNewContext()
{
  DBG_fprintf(stderr, "OpenGL Text: new context, forgetting fonts.\n");
  textListHaveBeenBuilt = FALSE;
}
