

/* 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 from gtkglext  taken from:

 * example/font.c:
 * Simple example for text rendering with PangoFT2.
 * License: LGPL
 * Copyright: written by Naofumi Yasufuku  <naofumi@users.sourceforge.net>


 this code does not work very well and it does not support UTF-8
 */

#include "lightspeed.h"




gint my_gdk_string_width(PangoFontDescription *fontdesc,const gchar *text)
{
  gint width,height;
  g_return_val_if_fail(text,100);
  PangoLayout *layout = gtk_widget_create_pango_layout (usr_cams[0]->ogl_w, text);
  g_return_val_if_fail(layout,100);
  pango_layout_set_font_description (layout, fontdesc); 
  pango_layout_get_pixel_size (layout, &width, &height);
  g_object_unref (layout);
  return width;
}



#include "gtkglext-workaround.c"

/* Draws a string in the viewport
 * Meaning of args can vary, see initial switch statement
 * "size" specifies size of text: 0 (small), 1 (medium) or 2 (large)
 * NOTE: This function requires some pre-existing state; namely, the target
 * GL context must already be made current as well as properly initialized
 * (see ogl_blank( ) or info_display( ) to see what I mean) */
void

ogl_draw_string( const void *data, int message, int size )
{
	static PangoFontDescription **fonts;
	static unsigned int *font_dlist_bases;
	static int *font_heights;
	static int width, height;
	static int fn_big;
	static int num_tl_lines, num_tr_lines, num_bl_lines, num_br_lines;
	static int num_cen_lines;
	const char *test_str = "XXXX XXXX XXXX XXXX";
	camera *cam;
	int pos_code;
	int edge_dx = 1, edge_dy = 1;
	int x = 0, y = 0;
	int fn;
	int i;
	char str_buf[256];
	char *disp_str;
	char *next_disp_str;

	switch (message) {
	case INITIALIZE:
		/* First-time initialization */
		fonts = xmalloc( num_font_sizes * sizeof(PangoFontDescription *));
		font_dlist_bases = xmalloc( num_font_sizes * sizeof(unsigned int *) );
		font_heights = xmalloc( num_font_sizes * sizeof(int *) );
		for (i = 0; i < num_font_sizes; i++) {
		  PangoFontDescription *font_descr = fonts[i] = pango_font_description_new();
		  /* Mennucc: according to 
		     http://developer.gnome.org/dotplan/porting/ar01s10.html
		     "Sans" is always guaranteed to exist  */
		  pango_font_description_set_family(font_descr,"Sans");
		  pango_font_description_set_size(font_descr,(i+10)*PANGO_SCALE);
		  font_dlist_bases[i] = glGenLists( 192 );
		  /* Mennucc: see in file gtkglext-workaround.c 
		     Also note that gdk_gl_font_use_pango_font relies on PangoX that
		     is now deprecated.
		  */
		  PangoFont  *pango_font = my_gdk_gl_font_use_pango_font(font_descr,
									 0,192,font_dlist_bases[i]);
		  if (pango_font == NULL) {
		    printf( "ERROR: Cannot load font: %s\n", 
			    pango_font_description_to_string(font_descr));
		    fflush( stdout );
		    continue;
		  }
		  PangoFontMetrics *font_metrics = pango_font_get_metrics (pango_font, NULL);
		  font_heights[i] = pango_font_metrics_get_ascent(font_metrics) +
		    pango_font_metrics_get_descent(font_metrics);
		  pango_font_metrics_unref(font_metrics);
		  pango_font_description_free(font_descr);		
		}
		return;

	case RESET:
		/* Once-per-GL-redraw initialization */
		g_return_if_fail(cam);
		cam = (camera *)data;
		/* Get GL widget dimensions */
		width = cam->width;
		height = cam->height;
		/* Reset line counters */
		num_tl_lines = 0;
		num_tr_lines = 0;
		num_bl_lines = 0;
		num_br_lines = 0;
		num_cen_lines = 0;
		/* Determine upper limit on the font sizes we should use */
		for (i = 0; i < num_font_sizes; i++) {
			fn_big = i; /* font number of "big" (size 2) font */
			/* Test string should be minimally 1/3 viewport width */
			if (my_gdk_string_width( fonts[i], test_str ) > (width / 3))
				break;
		}
		return;

	default:
		pos_code = message;
		disp_str = (char *)data;
		break;
	}
	g_return_if_fail(disp_str);
		
	/* Check string for newlines, and queue if necessary */
	i = strcspn( disp_str, "\n" );
	if (i < strlen( disp_str )) {
		strcpy( str_buf, disp_str );
		str_buf[i] = '\0';
		disp_str = str_buf;
		next_disp_str = &str_buf[i + 1];
	}
	else
		next_disp_str = NULL;

	/* Determine which (proportional) font size to use */
	fn = MIN(fn_big, MAX(0, fn_big - 2 + size)); /* 0 <= fn <= fn_big */

	/* 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 -= my_gdk_string_width( fonts[fn], disp_str );
		edge_dx = -1;
		break;

	case POS_CENTER:
		x = width / 2;
		x -= my_gdk_string_width( fonts[fn], disp_str ) / 2;
		edge_dx = 0;
		break;

	default:
#ifdef DEBUG
		crash( "ogl_draw_string( ): invalid position code" );
#endif
		return;
	}

	/* 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 -= font_heights[fn];
		edge_dy = -1;
		break;

	case POS_CENTER:
		y = height / 2;
		y -= font_heights[fn] / 2;
		edge_dy = -1;
		break;
	}

	/* This makes multi-line readouts possible */
	switch (pos_code) {
	case POS_TOP_LEFT:
		y -= num_tl_lines * font_heights[fn];
		++num_tl_lines;
		break;

	case POS_TOP_RIGHT:
		y -= num_tr_lines * font_heights[fn];
		++num_tr_lines;
		break;

	case POS_BOTTOM_LEFT:
		y += num_bl_lines * font_heights[fn];
		++num_bl_lines;
		break;

	case POS_BOTTOM_RIGHT:
		y += num_br_lines * font_heights[fn];
		++num_br_lines;
		break;

	case POS_CENTER:
		y -= num_cen_lines * font_heights[fn];
		++num_cen_lines;
		break;
	}

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

	/* Draw text backing */
	glColor3f( INFODISP_TEXT_BACK_R, INFODISP_TEXT_BACK_G, INFODISP_TEXT_BACK_B );
	glRasterPos2i( x + edge_dx, y + edge_dy );
	glListBase( font_dlist_bases[fn] );
	glCallLists( strlen(disp_str), GL_UNSIGNED_BYTE, disp_str );

	/* Draw text face */
	glColor3f( INFODISP_TEXT_FRONT_R, INFODISP_TEXT_FRONT_G, INFODISP_TEXT_FRONT_B );
	glRasterPos2i( x, y );
	glCallLists( strlen(disp_str), GL_UNSIGNED_BYTE, disp_str );

	/* Finally, do next line if disp_str had newlines */
	if (next_disp_str != NULL)
		ogl_draw_string( next_disp_str, pos_code, size );
}
