/******************************************************************************************
	AM2 PS   (c) 1999-2001 ISL

	psfont.c:			Font support
******************************************************************************************/

//#include "..\shell\shell.h"
//#include "..\isltex\isltex.h"
//#include "..\islmem\islmem.h"
//#include "..\islfile\islfile.h"
//#include "islfont.h"
#include "include.h"
#include "main.h"

// Richard's funky macros for calculating vram related stuff

#define VRAM_PAGECOLS		8
#define VRAM_PAGEROWS		2
#define VRAM_PAGES			16
#define VRAM_PAGEW			32
#define VRAM_PAGEH			32
#define VRAM_SETX(X)		(X)
#define VRAM_SETY(Y)		((Y)*VRAM_PAGEW)
#define VRAM_SETXY(X,Y)		((X)+((Y)*VRAM_PAGEW))
#define VRAM_SETPAGE(P)		((P)<<16)
#define VRAM_GETX(HND)		((HND) & (VRAM_PAGEW-1))
#define VRAM_GETY(HND)		(((HND)/VRAM_PAGEW) & (VRAM_PAGEW-1))
#define VRAM_GETXY(HND)		((HND) & 0xffff)
#define VRAM_GETPAGE(HND)	((HND)>>16)
#define VRAM_CALCVRAMX(HND)	(512+((VRAM_GETPAGE(HND)%(VRAM_PAGECOLS))*64)+(VRAM_GETX(HND)*2))
#define VRAM_CALCVRAMY(HND)	(((VRAM_GETPAGE(HND)/(VRAM_PAGECOLS))*256)+(VRAM_GETY(HND)*8))

#define ANG2FIX(a)		(((a)*4096)/360)

static TextureType	*buttonSprites[4];

static TextureType	*otherSprites[16];
static char			otherChars[16];
static int			numOtherSprites;
static UBYTE			redidx[16];
static UBYTE			greenidx[16];
static UBYTE			blueidx[16];

unsigned short *palPtr;
int tempx = 0;



unsigned char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-=+[]{}:;\"'|\\,<.>/?"
					"\xe0\xe8\xec\xf2\xf9\xc0\xc8\xcc\xd2\xd9\xe1\xe9\xed\xf3\xfa\xfd\xc1\xc9\xcd\xd3\xda\xdd\xe2\xea\xee\xf4\xfb\xc2\xca\xce\xd4\xdb\xe3\xf1\xf5\xc3\xd1\xd5\xe4\xeb\xef\xf6\xfc\xff\xc4\xcb\xcf\xd6\xdc\xe5\xc5\xe6\xc6\xe7\xc7\xf0\xd0\xf8\xd8\xbf\xa1\xdf";


static void fontDispSprite(TextureType *tex, short x,short y);


//PRINT FUNCTIONS//////////////////////////////////////////////////////////////////////////////////////////////////////
static void fontDispChar(TextureType *tex, short x,short y, unsigned char r, unsigned char g, unsigned char b, unsigned char alpha)
{
   	POLY_GT4 	*si; 
	int w,h;

	w=tex->u3*1.25;//tex->w;
	h=tex->v3*1.875;//tex->h;

	BEGINPRIM(si, POLY_GT4);

	setPolyGT4(si);

	si->tpage = tex->tpage;

	setXY4(si,
			x  ,y,
			x+w,y,
			x,  y+h,
			x+w,y+h);
	setUV4(si, 
			tex->u0, tex->v0,
			tex->u1, tex->v1,
			tex->u2, tex->v2,
			tex->u3, tex->v3);
					    
	setRGB0(si,r,g,b);
	setRGB1(si,r,g,b);
	setRGB2(si,r,g,b);
	setRGB3(si,r,g,b);

	ENDPRIM(si, 1, POLY_GT4);
}


/**************************************************************************
	FUNCTION:	fontPrint()
	PURPOSE:	Display string in font at pos in colour
	PARAMETERS:	font ptr, x,y, string, r,g,b
	RETURNS:	
**************************************************************************/

void fontPrint(psFont *font, short x,short y, char *text, unsigned char r, unsigned char g, unsigned char b)
{
	unsigned char	*strPtr, c;
	int				cx,cy, loop;
	TextureType		*letter;

	x*=1.25; 
	y*=1.85;

	x+=320;
	y+=240;

	strPtr = text;
	cx = x;
	cy = y;
	while(*strPtr)
	{
		c = *strPtr;
		switch(c)
		{
		case '\n':
			y += font->height;
			cx = x;
			cy = y;
			break;
		case ' ':
			x += font->height/2;
			break;
		case '@':
			switch(*(strPtr+1))
			{
			case 'X':
			    fontDispSprite(buttonSprites[2], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[2]->w+6;
				break;
			case 'C':
			   	fontDispSprite(buttonSprites[1], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[1]->w+6;
				break;
			case 'S':
			   	fontDispSprite(buttonSprites[3], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[3]->w+6;
				break;
			case 'T':
			   	fontDispSprite(buttonSprites[0], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[0]->w+6;
				break;
			}

			for(loop = 0; loop < numOtherSprites; loop ++)
			{
				if((*(strPtr+1)) == otherChars[loop])
				{
					fontDispSprite(otherSprites[loop], x+3,y-3 + font->spriteYOffset);
					strPtr++;
					x += otherSprites[loop]->w+6;
					break;
				}
			}

			break;

		default:
			loop = font->charlookup[c];
			if (loop<font->numchars)
			{
//				letter = &font->txPtr[loop];
				letter = &DCKtextureList[loop];
//				if ((x>-350)&&(x<320))
				if ((x>-font->pixelwidth[loop])&&(x<640))
					fontDispChar(letter, x,y-((c>127)?(1):(0)), r,g,b, font->alpha);
				x += (font->pixelwidth[loop]+2)*1.25;
			}
		}
		strPtr++;
	}
}


/**************************************************************************
	FUNCTION:	fontExtentW()
	PURPOSE:	Get width of string using font
	PARAMETERS:	font ptr, string
	RETURNS:	Width in pixels
**************************************************************************/

int fontExtentW(psFont *font, char *text)
{
	unsigned char	*strPtr, c;
	int		loop, x, maxW = 0;

	strPtr = text;
	x = 0;
	while(*strPtr)
	{
		c = *strPtr;
		switch(c)
		{
		case '\n':
			if (x>maxW)
				maxW = x;
			x = 0;
			break;
		case ' ':
			x += font->height/2;
			break;
		case '@':
			switch(*(strPtr+1))
			{
			case 'X':
				strPtr++;
				x += buttonSprites[2]->w+6;
				break;
			case 'C':
				strPtr++;
				x += buttonSprites[1]->w+6;
				break;
			case 'S':
				strPtr++;
				x += buttonSprites[3]->w+6;
				break;
			case 'T':
				strPtr++;
				x += buttonSprites[0]->w+6;
				break;
			}

			for(loop = 0; loop < numOtherSprites; loop ++)
			{
				if((*(strPtr+1)) == otherChars[loop])
				{
					strPtr++;
					x += otherSprites[loop]->w+6;
					break;
				}
			}

			break;
		default:
			loop = font->charlookup[c];
			if (loop<font->numchars)
				x += font->pixelwidth[loop]+2;
		}
		strPtr++;
	}
	if (x>maxW)
		maxW = x;
	return maxW;
}


/**************************************************************************
	FUNCTION:	fontFitToWidth()
	PURPOSE:	Wrap string to width into buffer
	PARAMETERS:	font ptr, width, string, buffer
	RETURNS:	Number of lines
**************************************************************************/

int fontFitToWidth(psFont *font, int width, char *text, char *buffer)
{
	char	buf[256], *bufPtr, *outPtr = buffer;
	int		pixLen, lines = 0;

	memset(buf, 0, sizeof(buf));
	bufPtr = buf;
	while(1)
	{
		if (*text>=' ')
			*bufPtr++ = *text;
		pixLen = fontExtentW(font, buf);
		if ((pixLen>width)||(*text=='\0'))
		{
			if (pixLen>width)
			{
				while(*bufPtr!=' ')
				{
					bufPtr--;
					text--;
				}
				text++;
			}
			*bufPtr = '\0';
			strcpy(outPtr, buf);
			outPtr += strlen(buf)+1;
			lines++;
			bufPtr = buf;
			memset(buf, 0, sizeof(buf));
			if (*text=='\0')
				break;
		}
		text++;
	}
/*	debugPrintf("%d lines: \n", lines);
	outPtr = buffer;
	for(pixLen=0; pixLen<lines; pixLen++)
	{
		debugPrintf("  '%s'\n", outPtr);
		outPtr += strlen(outPtr)+1;
	}*/
	return lines;
}



/**************************************************************************
	FUNCTION:	fontPrintN()
	PURPOSE:	Display (partial) string in font at pos in colour
	PARAMETERS:	font ptr, x,y, string, r,g,b, max chars
	RETURNS:	
**************************************************************************/

void fontPrintN(psFont *font, short x,short y, char *text, unsigned char r, unsigned char g, unsigned char b, int n)
{
	unsigned char		*strPtr, c;
	int			cx,cy, loop;
	TextureType	*letter;

	strPtr = text;
	cx = x;
	cy = y;
	while ((*strPtr) && (n>0))
	{
		c = *strPtr;
		switch(c)
		{
		case '\n':
			y += font->height;
			cx = x;
			cy = y;
			break;
		case ' ':
			x += font->height/2;
			break;
		case '@':
			switch(*(strPtr+1))
			{
			case 'X':
			    fontDispSprite(buttonSprites[2], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[2]->w+6;
				break;
			case 'C':
			   	fontDispSprite(buttonSprites[1], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[1]->w+6;
				break;
			case 'S':
			   	fontDispSprite(buttonSprites[3], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[3]->w+6;
				break;
			case 'T':
			   	fontDispSprite(buttonSprites[0], x+3,y-3 + font->spriteYOffset);
				strPtr++;
				x += buttonSprites[0]->w+6;
				break;
			}

			for(loop = 0; loop < numOtherSprites; loop ++)
			{
				if((*(strPtr+1)) == otherChars[loop])
				{
					fontDispSprite(otherSprites[loop], x+3,y-3 + font->spriteYOffset);
					strPtr++;
					x += otherSprites[loop]->w+6;
					break;
				}
			}

			break;
		default:
			loop = font->charlookup[c];
			if (loop<font->numchars)
			{
				letter = &font->txPtr[loop];
				if ((x>-350)&&(x<320))
					fontDispChar(letter, x,y-((c>127)?(1):(0)), r,g,b,font->alpha);
				x += font->pixelwidth[loop]+2;
			}
		}
		strPtr++;
		n--;
	}
}

static void fontDispSprite(TextureType *tex, short x,short y)
{
	POLY_FT4 	*si;
	USHORT		w,h;

	
	BEGINPRIM(si, POLY_FT4);

	w = tex->w;
	
	if(buttonSprites[0]==tex || buttonSprites[1]==tex || buttonSprites[2]==tex || buttonSprites[3]==tex)
		h = tex->h;	 //don't need to stretch these!
	else
		h = tex->h*2;

	si->x0 = x;
	si->y0 = y;
	si->x1 = x+w-1;
	si->y1 = y;
	si->x2 = x;
	si->y2 = y+h-1;
	si->x3 = x+w-1;
	si->y3 = y+h-1;
		
	si->r0 = 128;
	si->g0 = 128;
	si->b0 = 128;
	si->u0 = tex->u0;
	si->v0 = tex->v0;
	si->u1 = tex->u1;
	si->v1 = tex->v1;
	si->u2 = tex->u2;
	si->v2 = tex->v2;
	si->u3 = tex->u3;
	si->v3 = tex->v3;
	si->tpage = tex->tpage;
	si->clut = tex->clut;
	setPolyFT4(si);
	ENDPRIM(si, 1, POLY_FT4);
}

void fontRegisterButtonSprites(TextureType *triangle, TextureType *circle, TextureType *cross, TextureType *square)
{
	buttonSprites[0] = triangle;
	buttonSprites[1] = circle;
	buttonSprites[2] = cross;
	buttonSprites[3] = square;
}

void fontRegisterOtherSprites(char code, TextureType *sprite)
{

	if(numOtherSprites < 16)
	{
		otherSprites[numOtherSprites] = sprite;
		otherChars[numOtherSprites] = code;
		numOtherSprites ++;
	}
}

//END PRINT FUNCTIONS//////////////////////////////////////////////////////////////////////////////////////////////////









static void fontDownload(psFont *font, char *fontdata, int character)
{
	int			    w,h;
	unsigned char	*offset;
	TextureType		*txPtr;
	int				palCounter = 0;
	int				loop, loop2, col1, totalIm = 0;
	int				imageLength = 0;
	short			surfaceW,surfaceH;
	USHORT			*pixelPtr,*bmapPtr,r,g,b;
  	KMSTATUS 		tflag;
	UBYTE			*pptr;
	int				colour,i,j;
	int				red[16],blue[16],green[16];

	//first, lets sort out the palette
	//palPtr points at the palette
	for(loop = 0; loop < 16 ; loop ++)
	{
		colour = palPtr[loop];

		red[loop]   = ((colour))&31;
		green[loop] = ((colour>>5))&31;
		blue[loop]  = ((colour>>10))&31;
	}

	w = (font->width[character]+7)/8;
	h = (font->height+7)/8;

	font->width[character] = ((font->width[character] + 3) & 0xfffffffc);

	w = font->width[character];
	h = font->height;

	//not expecting a font bigger than 64x64
	if(w <= 8)
		surfaceW = 8;
	else if(w <= 16)
		surfaceW = 16;
	else if(w <= 32)
		surfaceW = 32;
	else 
		surfaceW = 64;

	if(h <= 8)
		surfaceH = 8;
	else if(h <= 16)
		surfaceH = 16;
	else if(h <= 32)
		surfaceH = 32;
	else 
		surfaceH = 64;

	if(surfaceW > surfaceH)
		surfaceH = surfaceW;
	else	
		surfaceW = surfaceH;
				
	txPtr = &DCKtextureList[DCKnumTextures];

	//build my dc surface
	tflag = kmCreateTextureSurface(&txPtr->surface, surfaceW, surfaceH,KM_TEXTURE_ARGB1555|KM_TEXTURE_RECTANGLE);
	if(tflag != KMSTATUS_SUCCESS)
	{
		debug_printf("failed to build a font surface!\n");
		Align32Free(bmapPtr);
		return;
	}



	offset = fontdata + font->dataoffset[character];

	imageLength = ((int)font->height * (int)font->width[character]);

	bmapPtr = Align32Malloc(surfaceW*surfaceH*sizeof(USHORT));
	pixelPtr = bmapPtr;

	w+=3;
	w/=4;
	w*=4;

	h+=3;
	h/=4;
	h*=4;

	for(i=0;i<surfaceH;i++)
	{
		for(j=0;j<surfaceW;j++)
		{
			if(j<w && i<h)
			{
				col1 = (int)(*offset & 0xf);
				r = red[col1];
				g = green[col1];
				b = blue[col1];
				if((r > 20)&&(g < 10)&&(b > 20))
					pixelPtr[j+(i*surfaceH)] = RGBA1555(0,0,0,0);
				else
					pixelPtr[j+(i*surfaceH)] = RGBA1555(r,g,b,1);
				palCounter++;

				j++;

				col1 = (int)(*offset >> 4);
				r = red[col1];
				g = green[col1];
				b = blue[col1];
				if((r > 20)&&(g < 10)&&(b > 20))
					pixelPtr[j+(i*surfaceH)] = RGBA1555(0,0,0,0);
				else
					pixelPtr[j+(i*surfaceH)] = RGBA1555(r,g,b,1);
				palCounter++;
				  
				offset++;
				totalIm++;
			}
		}
	} 







	//copy to surface
	kmLoadTexture(&txPtr->surface, (PKMDWORD)bmapPtr);

	Align32Free(bmapPtr);

	txPtr->colourKey=TRUE;
	txPtr->surfacePtr = &txPtr->surface;
	txPtr->w = surfaceW;	
	txPtr->h = surfaceH;	
	txPtr->u0 = 0;
	txPtr->v0 = 0;
	txPtr->u2 = font->width[character];
	txPtr->v2 = 0;
	txPtr->u1 = 0;
	txPtr->v1 = font->height;
	txPtr->u3 = font->width[character];
	txPtr->v3 = font->height;
	txPtr->tpage = DCKnumTextures;

//	font->numchars=character;
	font->charlookup[alphabet[character]] = character;

	memcpy(&txPtr->stripHead,&StripHead_GT4_Alpha,sizeof(StripHead_GT4_Alpha));
	kmChangeStripTextureSurface(&txPtr->stripHead,KM_IMAGE_PARAM1,&txPtr->surface);

	DCKnumTextures++;
}
















psFont *fontLoad(char *fontname)
{
	int				loop,col;
	unsigned char	*fontdata;
	long			*fontptr;
	psFont			*fontl;
	int				filelength;

	fontl = (psFont *)MALLOC0(sizeof(psFont));
	gdFsChangeDir("\\");
	gdFsChangeDir("TEXTURES");
	debug_printf("name=%s\n",fontname);
	if((fontdata = (unsigned char*)fileLoad(fontname, &filelength))==NULL)
		return NULL;

//copied from neil
	fontptr = (int *)fontdata;
	fontl->numchars = *fontptr++;
	fontl->height = *fontptr++;
	palPtr = (unsigned short *)fontptr;

	fontptr = (int *)fontdata + 10;

	fontl->txPtr = (TextureType *)MALLOC(sizeof(TextureType)*fontl->numchars);
//	memset(fontl->charlookup, -1, 256);
	for(loop = 0; loop < fontl->numchars; loop++)
	{
		fontl->dataoffset[loop] = *fontptr++;
		fontl->width[loop] = *fontptr++;
		fontl->pixelwidth[loop] = *fontptr++;
		fontDownload(fontl, fontdata, loop);
//		fontl->charlookup[alphabet[loop]] = loop;
	}
	FREE(fontdata);

//	fontl->alpha = 0;
//


	return fontl;
}





















	


