//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------

#include "giofx.h"

static cTex text_tCoords[200];
static cVertex text_vCoords[200];
    
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
void cScene::DeleteFontMetric()
{
	SAFE_FREE(_charInfo);
	SAFE_FREE(_kerningPair);
}
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
void cScene::LoadFont(char* fontName,char* metrikName)
{

	if (pTexture[texFont])
	{
		delete pTexture[texFont];
		texFont = 0;
		DeleteFontMetric();
	}
	
	//carica la fonte --------------------------
	char filename[MAX_PATH];
	
    sprintf(filename,"%s",fontName);
    texFont = LoadTexture(filename);
    
    char metricname[MAX_PATH];
    sprintf(metricname,"%s%s",this->dataPath,metrikName);

	//carica la metrica ------------------------
	FILE* ff = NULL;
	if ((ff = fopen(metricname,"rb")) == NULL)
    {
        printf("ERROR OPENING %s \n",metricname);
		return;
	}
    
	BYTE b[5];
	fread(&b,sizeof(BYTE),4,ff); //"BMF" + versione "1" o "2"

	BYTE blockId;
	int  blockSize;
	while(fread(&blockId,sizeof(BYTE),1,ff)) //id blocco
	{
		fread(&blockSize,sizeof(int),1,ff);  //lunghezza blocco (int incluso)
		blockSize -= 4;

		if (blockId == 1) //il block #1 viene skippato
			fseek(ff,blockSize ,SEEK_CUR);

		if (blockId == 2) //il block #2 viene skippato
			fseek(ff,blockSize,SEEK_CUR);

		if (blockId == 3) //il block #3 viene skippato
			fseek(ff,blockSize,SEEK_CUR);

		if (blockId == 4) //il block #4 contiene dati sui caratteri
		{
			_numChar = blockSize / sizeof(charInfo);
			_charInfo = (charInfo*)malloc(_numChar * sizeof(charInfo));
			for (int i=0;i<_numChar;i++)
				fread(&_charInfo[i],sizeof(charInfo),1,ff);
		}

		if (blockId == 5) //il block #4 contiene eventuali kernings
		{
			_numKern = blockSize / sizeof(kerningPair);
			_kerningPair = (kerningPair*)malloc(4 + _numKern * sizeof(kerningPair));
			for (int i=0;i<_numKern;i++)
				fread(&_kerningPair[i],sizeof(kerningPair),1,ff);
		}

	}
	fclose(ff);
}
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
void cScene::DrawChars(float iX,float iY,float iZ,float xSize,float ySize,char *writeIn,float r,float g,float b,float a)
{	
	if (!_charInfo)
		return;
		
	glPushMatrix();

	glBindTexture(GL_TEXTURE_2D,pTexture[texFont]->memAddr);
	glColor4f(r,g,b,a);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glTranslatef(iX,iY,iZ);

	glScalef(xSize,ySize,1);
	
    float texSizeX     = (float)pTexture[texFont]->size.h;
	float texSizeY     = (float)pTexture[texFont]->size.v;
	float posX         = 0;
	
	int u = 0;
	for (int t=0;t<(int)strlen(writeIn);t++)
		for (int i=0;i<_numChar;i++)
			if (_charInfo[i].id == writeIn[t])
			{
				//posizione (via _charInfo*)
				//x			The left position of the character image in the texture.
				//y			The top position of the character image in the texture.
				//width		The width of the character image in the texture.
				//height	The height of the character image in the texture.
				//xoffset	How much the current position should be offset when copying the image from the texture to the screen.
				//yoffset	How much the current position should be offset when copying the image from the texture to the screen.
				//xadvance	How much the current position should be advanced after drawing the character.
				
				float sx        = (float)(_charInfo[i].x)       / texSizeX;
				float sy        = (float)(_charInfo[i].y)       / texSizeY;
				float width     = (float)(_charInfo[i].width)   / texSizeX;
				float height    = (float)(_charInfo[i].height)  / texSizeY;
				float offsx     = (float)_charInfo[i].xoffset;
				float offsy     = (float)_charInfo[i].yoffset;

				sy = 1.0 - sy;
                
                //texcoord
                text_tCoords[u+0].Set(sx,           sy);          
                text_tCoords[u+1].Set(sx+width,     sy);
                text_tCoords[u+2].Set(sx+width,     sy-height);
                text_tCoords[u+3].Set(sx,           sy);   
                text_tCoords[u+4].Set(sx+width,     sy-height);
                text_tCoords[u+5].Set(sx,           sy-height); 

                //vertici
                text_vCoords[u+0].Set(posX+offsx,                       offsy,          iZ);
                text_vCoords[u+1].Set(posX+_charInfo[i].width+offsx,	offsy,          iZ);
                text_vCoords[u+2].Set(posX+_charInfo[i].width+offsx,	_charInfo[i].height+offsy,   iZ);
                text_vCoords[u+3].Set(posX+offsx,                       offsy,          iZ);
                text_vCoords[u+4].Set(posX+_charInfo[i].width+offsx,	_charInfo[i].height+offsy,       iZ);
                text_vCoords[u+5].Set(posX+offsx,                       _charInfo[i].height+offsy,iZ);
                
                u+=6;
				posX += _charInfo[i].xadvance;
				
				//kerning (via _kerningPair*)
				//first		The first character id.
				//second	The second character id.
				//amount	How much the x position should be adjusted when drawing the second character immediately following the first.
				if (_kerningPair)
					if (t+1 < (int)strlen(writeIn))
						for (int k=0;k<_numKern;k++)
							if (_kerningPair[k].first  == writeIn[t] && 
								_kerningPair[k].second == writeIn[t+1])
                                {
                                    posX += _kerningPair[k].amount;
                                    break;
                                }
			}
    
    glTexCoordPointer(2,GL_FLOAT,0,text_tCoords);
    glVertexPointer(3,GL_FLOAT,0,text_vCoords);
    glDrawArrays(GL_TRIANGLES,0,u);
        
	glPopMatrix();
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glScalef(scale.x,scale.y,scale.z);
}
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
void cScene::Draw2DChars(float iX,float iY,float iZ,float scale,char *writeIn,float r,float g,float b,float a)
{
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glDepthMask(FALSE);

	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();

	glOrtho(0, resolutionX, resolutionY, 0,   -1,+1);

	DrawChars(iX, iY, iZ, scale, scale, writeIn, r, g, b, a);
	
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glDepthMask(TRUE);
}
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
void cScene::Draw3DChars(float iX,float iY,float iZ,float scale,char *writeIn,float r,float g,float b,float a)
{
	glRotatef(180,1,0,0);
	DrawChars(iX, iY, iZ, scale, scale, writeIn, r, g, b, a);
}
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
void cScene::DrawChars(float iX,float iY,char *writeIn,cColor& inColor){	

	DrawChars(iX,iY,-1,12,10,writeIn,inColor.r,inColor.g,inColor.b,inColor.a);	
}
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
void cScene::DrawChars(cVertex v,char *writeIn,cColor& inColor){	

	DrawChars(v.x,v.y,v.z,12,10,writeIn,inColor.r,inColor.g,inColor.b,inColor.a);	
}
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------





