/**
 *******************************************************************************
 * @file ewolFontFreeType.cpp
 * @brief ewol Font system wrapper on freetype(sources)
 * @author Edouard DUPIN
 * @date 05/11/2011
 * @par Project
 * ewol
 *
 * @par Copyright
 * Copyright 2011 Edouard DUPIN, all right reserved
 *
 * This software is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY.
 *
 * Licence summary : 
 *    You can modify and redistribute the sources code and binaries.
 *    You can send me the bug-fix
 *
 * Term of the licence in in the file licence.txt.
 *
 *******************************************************************************
 */


#include <ewolFont.h>
#include <ewolTexture.h>
#include <etkVectorType.h>


#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
#include <GL/glut.h>
#if defined(EWOL_X11_MODE__XF86V)
#	include <X11/extensions/xf86vmode.h>
#elif defined(EWOL_X11_MODE__XRENDER)
#	include <X11/extensions/Xrender.h>
#endif


#include <ft2build.h>
#include FT_FREETYPE_H

#undef __class__
#define __class__	"ewol::FontFreeType"



extern "C"
{
	typedef struct {
		uniChar_t   unicodeCharVal;
		int32_t     width;
		texCoord_ts posStart;
		texCoord_ts posStop;
		etkFloat_t ratio;
	}freeTypeFontElement_ts;
};

// free Font hnadle of librairies ... entry for acces ...
static FT_Library library;

static int32_t nextP2(int32_t value)
{
	int32_t val=1;
	for (int32_t iii=1; iii<31; iii++) {
		if (value <= val) {
			return val;
		}
		val *=2;
	}
	EWOL_CRITICAL("impossible CASE....");
	return val;
}

static int32_t simpleSQRT(int32_t value)
{
	int32_t val=1;
	for (int32_t iii=1; iii<1000; iii++) {
		val =iii*iii;
		if (value <= val) {
			return iii;
		}
	}
	EWOL_CRITICAL("impossible CASE....");
	return val;
}

void ewol::InitFont(void)
{
	int32_t error = FT_Init_FreeType( &library );
	if(0 != error) {
		EWOL_CRITICAL(" when loading FreeType Librairy ...");
	}
}

// keep only one instance of every font in freetype
class FTFontInternal
{
	private:
		void Display(void)
		{
			EWOL_INFO("    nuber of glyph       = " << m_fftFace->num_glyphs);
			if ((FT_FACE_FLAG_SCALABLE & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_SCALABLE (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_SCALABLE (disable)");
			}
			if ((FT_FACE_FLAG_FIXED_SIZES & m_fftFace->face_flags) != 0) {
					EWOL_INFO("    flags                = FT_FACE_FLAG_FIXED_SIZES (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_FIXED_SIZES (disable)");
			}
			if ((FT_FACE_FLAG_FIXED_WIDTH & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_FIXED_WIDTH (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_FIXED_WIDTH (disable)");
			}
			if ((FT_FACE_FLAG_SFNT & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_SFNT (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_SFNT (disable)");
			}
			if ((FT_FACE_FLAG_HORIZONTAL & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_HORIZONTAL (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_HORIZONTAL (disable)");
			}
			if ((FT_FACE_FLAG_VERTICAL & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_VERTICAL (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_VERTICAL (disable)");
			}
			if ((FT_FACE_FLAG_KERNING & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_KERNING (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_KERNING (disable)");
			}
			/* Deprecated flag
			if ((FT_FACE_FLAG_FAST_GLYPHS & face->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_FAST_GLYPHS (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_FAST_GLYPHS (disable)");
			}
			*/
			if ((FT_FACE_FLAG_MULTIPLE_MASTERS & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_MULTIPLE_MASTERS (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_MULTIPLE_MASTERS (disable)");
			}
			if ((FT_FACE_FLAG_GLYPH_NAMES & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_GLYPH_NAMES (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_GLYPH_NAMES (disable)");
			}
			if ((FT_FACE_FLAG_EXTERNAL_STREAM & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_EXTERNAL_STREAM (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_EXTERNAL_STREAM (disable)");
			}
			if ((FT_FACE_FLAG_HINTER & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_HINTER (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_HINTER (disable)");
			}
			if ((FT_FACE_FLAG_CID_KEYED & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_CID_KEYED (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_CID_KEYED (disable)");
			}
			if ((FT_FACE_FLAG_TRICKY & m_fftFace->face_flags) != 0) {
				EWOL_INFO("    flags                = FT_FACE_FLAG_TRICKY (enable)");
			} else {
				EWOL_DEBUG("    flags                = FT_FACE_FLAG_TRICKY (disable)");
			}
			EWOL_INFO("    unit per EM          = " << m_fftFace->units_per_EM);
			EWOL_INFO("    num of fixed sizes   = " << m_fftFace->num_fixed_sizes);
			EWOL_INFO("    Availlable sizes     = " << m_fftFace->available_sizes);
			
			EWOL_INFO("    Current size         = " << m_fftFace->size);
		}
	public:
		FTFontInternal(etk::File fontFileName, etk::String fontName)
		{
			m_fontName = fontName;
			m_fileName = fontFileName;
			int32_t error = FT_New_Face( library, m_fileName.GetCompleateName().c_str(), 0, &m_fftFace );
			if( FT_Err_Unknown_File_Format == error) {
				EWOL_ERROR("... the font file could be opened and read, but it appears ... that its font format is unsupported");
			} else if (0 != error) {
				EWOL_ERROR("... another error code means that the font file could not ... be opened or read, or simply that it is broken...");
			} else {
				// all OK
				EWOL_INFO("load font : \"" << m_fileName << "\" ");
				Display();
			}
		}
		~FTFontInternal(void)
		{
			
		}
	public:
		etk::String GetFontName(void) {return m_fontName;};
		bool GenerateBitmapFont(int32_t size, int32_t &height, int32_t textureId, etk::VectorType<freeTypeFontElement_ts> & listElement)
		{
			// 300dpi (hight quality) 96 dpi (normal quality)
			int32_t fontQuality = 96;
			//int32_t fontQuality = 300;
			// Select Size ...
			// note tha <<6==*64 corespond with the 1/64th of points calculation of freetype
			int32_t error = FT_Set_Char_Size(m_fftFace, size<<6, size<<6, fontQuality, fontQuality);
			// the line height to have a correct display
			height = size*1.43f;

			// a small shortcut
			FT_GlyphSlot slot = m_fftFace->glyph;
			
			EWOL_DEBUG("Max size for ths glyph size=" << size << " is (" << m_fftFace->max_advance_width << "," << m_fftFace->max_advance_height << ")");
			
			// retrieve glyph index from character code 
			int32_t glyph_index = FT_Get_Char_Index(m_fftFace, 'A' );
			// load glyph image into the slot (erase previous one)
			error = FT_Load_Glyph(m_fftFace, // handle to face object
			                      glyph_index, // glyph index
			                      FT_LOAD_DEFAULT );
			if ( error ) {
				EWOL_ERROR("FT_Load_Glyph");
			}
			EWOL_DEBUG("linearHoriAdvance=" << (slot->linearHoriAdvance >> 6));
			EWOL_DEBUG("linearVertAdvance=" << (slot->linearVertAdvance >> 6));
			EWOL_DEBUG("metrics.horiAdvance=" << (slot->metrics.horiAdvance >> 6));
			EWOL_DEBUG("metrics.vertAdvance=" << (slot->metrics.vertAdvance >> 6));
			
			int32_t nbElement = listElement.Size();
			int32_t coter = simpleSQRT(nbElement);
			int32_t glyphMaxWidth = slot->metrics.horiAdvance>>6;
			int32_t glyphMaxHeight = slot->metrics.vertAdvance>>6;
			int32_t textureWidth = nextP2(coter*glyphMaxWidth);
			int32_t nbRaws = textureWidth / glyphMaxWidth;
			int32_t nbLine = (nbElement / nbRaws) + 1;
			int32_t textureHeight = nextP2(nbLine*glyphMaxHeight);
			EWOL_DEBUG("Generate a text texture for char(" << nbRaws << "," << nbLine << ") with size=(" << textureWidth << "," << textureHeight << ")");
			
			// Allocate Memory For The Texture Data.
			GLubyte* expanded_data = new GLubyte[ 2 * textureWidth * textureHeight];
			// clean the data : 
			for(int j=0; j <textureHeight;j++) {
				for(int i=0; i < textureWidth; i++){
					expanded_data[2*(i+j*textureWidth)+0] = 0;
					expanded_data[2*(i+j*textureWidth)+1] = 0;
				}
			}
			
			int32_t tmpRowId = 0;
			int32_t tmpLineId = 0;
			// Generate for All Elements :
			for (int32_t iii=0; iii<listElement.Size(); iii++) {
				// increment the position of the texture
				if (iii!=0) {
					tmpRowId++;
					if (tmpRowId>=nbRaws) {
						tmpRowId = 0;
						tmpLineId++;
					}
				}
				// retrieve glyph index from character code 
				glyph_index = FT_Get_Char_Index(m_fftFace, listElement[iii].unicodeCharVal );
				// load glyph image into the slot (erase previous one)
				error = FT_Load_Glyph(m_fftFace, // handle to face object
				                      glyph_index, // glyph index
				                      FT_LOAD_DEFAULT );
				if ( error ) {
					EWOL_ERROR("FT_Load_Glyph");
				}
				
				// convert to an anti-aliased bitmap
				error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL );
				if ( error ) {
					EWOL_ERROR("FT_Render_Glyph");
				}
				int32_t tmpWidth=slot->bitmap.width;
				int32_t tmpHeight=slot->bitmap.rows;
				/*
				EWOL_DEBUG("elem=" << listElement[iii].unicodeCharVal
				           <<" size=(" << tmpWidth << "," << tmpHeight << ")"
				           << " for bitmap (left=" << slot->bitmap_left << ",top=" << slot->bitmap_top << ")");
				EWOL_DEBUG(" BEARING=(" << (slot->metrics.horiBearingX>>6) << "," << (slot->metrics.vertBearingY>>6) << ")" );
				*/
				for(int32_t j=0; j < tmpHeight;j++) {
					for(int32_t i=0; i < tmpWidth; i++){
						int32_t position = 2*(   (tmpRowId *glyphMaxWidth  + i /*+ (slot->metrics.horiBearingX>>6)*/ )
						                       + (tmpLineId*glyphMaxHeight + j + (size-(slot->metrics.horiBearingY>>6)) ) * textureWidth);
						expanded_data[position+0] = slot->bitmap.buffer[i + tmpWidth*j];
						expanded_data[position+1] = slot->bitmap.buffer[i + tmpWidth*j];
					}
				}
				listElement[iii].width = glyphMaxWidth;
				listElement[iii].posStart.u = (etkFloat_t)(tmpRowId *glyphMaxWidth) / (etkFloat_t)textureWidth;
				listElement[iii].posStart.v = (etkFloat_t)(tmpLineId*glyphMaxHeight) / (etkFloat_t)textureHeight;
				listElement[iii].posStop.u = (etkFloat_t)(tmpRowId *glyphMaxWidth + glyphMaxWidth) / (etkFloat_t)textureWidth;;
				listElement[iii].posStop.v = (etkFloat_t)(tmpLineId*glyphMaxHeight + glyphMaxHeight) / (etkFloat_t)textureHeight;
			}
			// Now We Just Setup Some Texture Parameters.
			glBindTexture( GL_TEXTURE_2D, textureId);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
			
			// Here We Actually Create The Texture Itself, Notice That We Are Using GL_LUMINANCE_ALPHA To Indicate That we Are Using 2 Channel Data.
			glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data );
			
			// With The Texture Created, We Don't Need The Expanded Data Anymore.
			delete [] expanded_data;
		
			return false;
		}
	private:
		etk::String  m_fontName;
		etk::File    m_fileName;
		FT_Face      m_fftFace;
};

static etk::VectorType<FTFontInternal*> m_listLoadedTTFont;


static etk::String s_currentFolderName = "";
static etk::String s_currentDefaultFontName = "";
static int32_t s_currentDefaultFontId = -1;

class FTFont{
	public:
		FTFont(etk::File fontfileName, etk::String fontName, int32_t size)
		{
			m_trueTypeFontId = -1;
			for (int32_t iii=0; iii < m_listLoadedTTFont.Size(); iii++) {
				if (m_listLoadedTTFont[iii]->GetFontName() == fontName) {
					m_trueTypeFontId = iii;
				}
			}
			if (-1==m_trueTypeFontId) {
				// load a new one ...
				FTFontInternal * tmpElement = new FTFontInternal(fontfileName, fontName);
				m_listLoadedTTFont.PushBack(tmpElement);
				m_trueTypeFontId = m_listLoadedTTFont.Size() -1;
			}
			// set the bassic charset:
			m_elements.Clear();
			freeTypeFontElement_ts tmpchar1;
			tmpchar1.unicodeCharVal = 0;
			m_elements.PushBack(tmpchar1);
			for (int32_t iii=0x20; iii<127; iii++) {
				freeTypeFontElement_ts tmpchar;
				tmpchar.unicodeCharVal = iii;
				m_elements.PushBack(tmpchar);
			}
			m_size = size;
			//generate font
			glGenTextures(1, &m_textureId);
			m_listLoadedTTFont[m_trueTypeFontId]->GenerateBitmapFont(m_size, m_lineHeight, m_textureId, m_elements);
		}
		~FTFont(void)
		{
			
		}
		bool Check(etk::String fontName, int32_t size)
		{
			if (m_trueTypeFontId == -1) {
				return false;
			}
			if(    m_listLoadedTTFont[m_trueTypeFontId]->GetFontName() == fontName
			    && m_size == size)
			{
				return true;
			}
			return false;
		};
		
		etk::VectorType<freeTypeFontElement_ts> & GetRefOnElement(void)
		{
			return m_elements;
		};
		
		uint32_t GetOglId(void)
		{
			return m_textureId;
		};
		
		int32_t GetSize(void)
		{
			return m_size;
		};
		
		int32_t GetHeight(void)
		{
			return m_lineHeight;
		};
		
	private:
		int32_t                                   m_trueTypeFontId;
		uint32_t                                  m_textureId;   // internal texture ID
		int32_t                                   m_size;        // nb pixel height
		int32_t                                   m_lineHeight;  // nb pixel height
		int32_t                                   m_interline;   // nb pixel between 2 lines
		etk::VectorType<freeTypeFontElement_ts>   m_elements;    // 
		
};

static etk::VectorType<FTFont*> m_listLoadedFont;

#undef __class__
#define __class__	"ewol::FontFreeType"

void ewol::SetFontFolder(etk::String folderName)
{
	if (s_currentFolderName != "") {
		EWOL_WARNING("Change the FontFolder, old=\"" << s_currentFolderName << "\"");
	}
	EWOL_TODO("Check if folder exist");
	s_currentFolderName = folderName;
	EWOL_INFO("New default font folder name=\"" << s_currentFolderName << "\"");
}


void ewol::UnInitFont(void)
{
	EWOL_TODO("later");
}

void ewol::SetDefaultFont(etk::String fontName, int32_t size)
{
	if (s_currentDefaultFontName != "") {
		EWOL_WARNING("Change the default Ewol Font, old=\"" << s_currentDefaultFontName << "\"");
	}
	EWOL_INFO("New default Font Name=\"" << fontName << "\"");
	int32_t tmpId = ewol::LoadFont(fontName, size);
	if (-1 == tmpId) {
		if (s_currentDefaultFontName == "") {
			EWOL_ASSERT(-1 != tmpId, "Error to load the default Font\"" << fontName << "\"");
		} else {
			EWOL_CRITICAL("Unable to load the new default font:\"" << fontName << "\"");
		}
		return;
	}
	// save the default font parameters ...
	s_currentDefaultFontName = fontName;
	s_currentDefaultFontId = tmpId;
}

int32_t ewol::GetDefaultFontId(void)
{
	return s_currentDefaultFontId;
}

int32_t ewol::LoadFont(etk::String fontName, int32_t size)
{
	// check if folder file
	etk::String tmpFileName = s_currentFolderName + "/" + fontName + ".ttf";
	etk::File fileName(tmpFileName);
	if (false == fileName.Exist()) {
		EWOL_ERROR("Font does not exist: \"" << fileName.GetCompleateName() << "\"");
		return -1;
	}
	for (int32_t iii=0; iii < m_listLoadedFont.Size(); iii++) {
		if (true == m_listLoadedFont[iii]->Check(fontName, size)) {
			return iii;
		}
	}
	FTFont * tmpFont = new FTFont(fileName, fontName, size);
	m_listLoadedFont.PushBack(tmpFont);
	return m_listLoadedFont.Size()-1;
}

void ewol::UnloadFont(int32_t id)
{
	EWOL_TODO("I do not think it was a good idea... will be done later");
}





void ewol::DrawText(int32_t                        fontID,
                    coord2D_ts &                   drawPosition,
                    const uniChar_t *              unicodeString,
                    uint32_t &                     fontTextureId,
                    etk::VectorType<coord2D_ts> &  coord,
                    etk::VectorType<texCoord_ts> & coordTex)
{
	if(fontID>=m_listLoadedFont.Size() || fontID < 0) {
		EWOL_WARNING("try to display text with an fontID that does not existed " << fontID);
		return;
	}
	etk::VectorType<freeTypeFontElement_ts> & listOfElement = m_listLoadedFont[fontID]->GetRefOnElement();
	
	fontTextureId = m_listLoadedFont[fontID]->GetOglId();
	int32_t size = m_listLoadedFont[fontID]->GetSize();
	
	etkFloat_t posDrawX = drawPosition.x;
	while(*unicodeString != 0) {
		int32_t tmpChar = *unicodeString++;
		if (tmpChar >= 0x80) {
			tmpChar = 0;
		}
		etkFloat_t sizeWidth = listOfElement[tmpChar].width;
		if (tmpChar != 0x20) {
			// set texture coordonates :
			coordTex.PushBack(listOfElement[tmpChar].posStart);
			texCoord_ts tmpTex;
			tmpTex.u = listOfElement[tmpChar].posStop.u;
			tmpTex.v = listOfElement[tmpChar].posStart.v;
			coordTex.PushBack(tmpTex);
			coordTex.PushBack(listOfElement[tmpChar].posStop);
			tmpTex.u = listOfElement[tmpChar].posStart.u;
			tmpTex.v = listOfElement[tmpChar].posStop.v;
			coordTex.PushBack(tmpTex);
			// set display positions :
			coord2D_ts tmpCoord;
			tmpCoord.x = posDrawX;
			tmpCoord.y = drawPosition.y;
			coord.PushBack(tmpCoord);
			tmpCoord.x = posDrawX + sizeWidth;
			coord.PushBack(tmpCoord);
			tmpCoord.y = drawPosition.y + size;
			coord.PushBack(tmpCoord);
			tmpCoord.x = posDrawX;
			coord.PushBack(tmpCoord);
		}
		posDrawX += sizeWidth;
	}
	drawPosition.x = posDrawX;
}



void ewol::DrawText(int32_t                        fontID,
                    coord2D_ts &                   drawPosition,
                    const char *                   utf8String,
                    uint32_t &                     fontTextureId,
                    etk::VectorType<coord2D_ts> &  coord,
                    etk::VectorType<texCoord_ts> & coordTex)
{
	// TODO : This code des not work, why ????
	/*
	int32_t tmpstringLen = strlen(utf8String);
	int32_t * tmpUnicodeString = new int32_t(tmpstringLen+1);
	// TODO : generate a better convertor...
	for (int32_t iii=0; iii<tmpstringLen; iii++) {
		tmpUnicodeString[iii] = utf8String[iii];
	}
	tmpUnicodeString[tmpstringLen] = 0;
	// unicode display ...
	//DrawText(fontID, drawPosition, tmpUnicodeString, fontTextureId, coord, coordTex);
	// clean temporary data ..
	delete [] tmpUnicodeString;
	*/
	if(fontID>=m_listLoadedFont.Size() || fontID < 0) {
		EWOL_WARNING("try to display text with an fontID that does not existed " << fontID);
		return;
	}
	etk::VectorType<freeTypeFontElement_ts> & listOfElement = m_listLoadedFont[fontID]->GetRefOnElement();
	char * tmpVal = (char*)utf8String;
	
	fontTextureId = m_listLoadedFont[fontID]->GetOglId();
	int32_t size = m_listLoadedFont[fontID]->GetSize();
	
	etkFloat_t posDrawX = drawPosition.x;
	while(*tmpVal != 0) {
		int32_t tmpChar = *tmpVal++;
		int32_t charIndex;
		if (tmpChar >= 0x80) {
			charIndex = 0;
		} else if (tmpChar < 0x20) {
			charIndex = 0;
		} else if (tmpChar < 0x80) {
			charIndex = tmpChar - 0x1F;
		} else {
			for (int32_t iii=0x80-0x20; iii < listOfElement.Size(); iii++) {
				if (listOfElement[iii].unicodeCharVal == tmpChar) {
					charIndex = iii;
					break;
				}
			}
			// TODO : Update if possible the mapping
			charIndex = 0;
		}
		etkFloat_t sizeWidth = listOfElement[charIndex].width;
		// 0x01 == 0x20 == ' ';
		if (tmpChar != 0x01) {
			// set texture coordonates :
			coordTex.PushBack(listOfElement[charIndex].posStart);
			texCoord_ts tmpTex;
			tmpTex.u = listOfElement[charIndex].posStop.u;
			tmpTex.v = listOfElement[charIndex].posStart.v;
			coordTex.PushBack(tmpTex);
			coordTex.PushBack(listOfElement[charIndex].posStop);
			tmpTex.u = listOfElement[charIndex].posStart.u;
			tmpTex.v = listOfElement[charIndex].posStop.v;
			coordTex.PushBack(tmpTex);
			// set display positions :
			coord2D_ts tmpCoord;
			tmpCoord.x = posDrawX;
			tmpCoord.y = drawPosition.y;
			coord.PushBack(tmpCoord);
			tmpCoord.x = posDrawX + sizeWidth;
			coord.PushBack(tmpCoord);
			tmpCoord.y = drawPosition.y + size;
			coord.PushBack(tmpCoord);
			tmpCoord.x = posDrawX;
			coord.PushBack(tmpCoord);
		}
		posDrawX += sizeWidth;
	}
	drawPosition.x = posDrawX;
	
}

int32_t ewol::GetWidth(int32_t fontID, const char * utf8String)
{
	if(fontID>=m_listLoadedFont.Size() || fontID < 0) {
		EWOL_WARNING("try to display text with an fontID that does not existed " << fontID);
		return 0;
	}
	etk::VectorType<freeTypeFontElement_ts> & listOfElement = m_listLoadedFont[fontID]->GetRefOnElement();
	char * tmpVal = (char*)utf8String;
	
	etkFloat_t posDrawX = 0.0;
	while(*tmpVal != 0) {
		int32_t tmpChar = *tmpVal++;
		int32_t charIndex;
		if (tmpChar >= 0x80) {
			charIndex = 0;
		} else if (tmpChar < 0x20) {
			charIndex = 0;
		} else if (tmpChar < 0x80) {
			charIndex = tmpChar - 0x1F;
		} else {
			for (int32_t iii=0x80-0x20; iii < listOfElement.Size(); iii++) {
				if (listOfElement[iii].unicodeCharVal == tmpChar) {
					charIndex = iii;
					break;
				}
			}
			// TODO : Update if possible the mapping
			charIndex = 0;
		}
		posDrawX += listOfElement[charIndex].width;
	}
	return posDrawX;
}

int32_t ewol::GetHeight(int32_t fontID)
{
	if(fontID>=m_listLoadedFont.Size() || fontID < 0) {
		EWOL_WARNING("try to display text with an fontID that does not existed " << fontID);
		return 10;
	}
	return m_listLoadedFont[fontID]->GetHeight();
}