#define MAX_FONT_TEXTURES 128

class FontTexture
{
		DWORD dwSize;
		int iFontHeight;
		int iNumRows;
		DWORD *dwSpaceAvailableOnEachRow;
		BYTE *pTexture;
		DWORD *p32BitTexture;
		bool b32Bit;
		void AddCharToTexture(BYTE *pData,DWORD dwWidth,DWORD dwX,DWORD dwY);
	public:
		FontTexture(DWORD dwSize,int iFontHeight);
		FontTexture(HFILE hFile,int iFontHeight,bool b32Bit);
		~FontTexture();
		bool AddChar(BYTE *pData,DWORD dwWidth,DWORD &dwXPos,DWORD &dwYPos);
		bool Save(HFILE hFile);
		bool Load(HFILE hFile);
		BYTE *GetCharMap(int iX, int iY, int iW);
		void SetCharMap(BYTE *pData,int iX, int iY, int iW) {AddCharToTexture(pData,(DWORD)iW,(DWORD)iX,(DWORD)iY);}
		BYTE *GetTexture() {return pTexture;}
		BYTE *Get32BitTexture() {return (BYTE *)p32BitTexture;}
		void ChangeFontHeight(int iNewHeight) {iFontHeight = iNewHeight;}
		DWORD Size() {return dwSize;}
		bool ExportTGA(const char *szFullPath);
		bool ImportTGA(const char *szFullPath);
};

typedef struct 
{
	BYTE *pData;
	BYTE bWidth;
	signed char aWidth;
	signed char cWidth;
	bool bUsed;
} CharData;

// structures for file format
#define D3DFONTSIG '4F3D'
#define D3D32BITFONTSIG 'TF3D'
#pragma warning( disable : 4200 ) 
typedef struct 
{
	DWORD dwSig;
	char szFaceName[64];
	int iSize; // point size of font used to create this font
	bool bItalic; // italic on or off when this font was created
	int iWeight; // weight of font created
	int iTextureCount; 
	DWORD dwFontHeight; // height in pixels of the resulatant font
	BYTE bTexture[256]; // indicate which texture each character is on
	BYTE bX[256]; // indicates x position of each character on it's texture
	BYTE bY[256]; // indicates y position of each character on it's texture
	BYTE bW[256]; // indicates width of each character in the texture
	signed char cA[256]; // indicates amount of space to add before each character (may be -)
	signed char cC[256]; // indicates amount of space to add after each character (may be -)
	//DWORD dwTextureOffsets[0]; // offsets to textures
} D3DFont;

typedef struct
{
	DWORD dwSize;
	BYTE bPixels[0];
} D3DFontTexture;

class Font
{
	protected:
		// temp data (used while building font, but not needed after font is built)
		CharData data[256];
		bool bMinimizeTextureCount;
		bool b32Bit;
		// intermediate data
		D3DFont header;
		int iNumTextures;
		int iTextureSize;
		FontTexture *pTextures[MAX_FONT_TEXTURES];

		void CalcAlphaAndAddChar(BYTE *pPixels,int width,int height,int num,int a, int c);
		void CalcAndAddChar(BYTE *pPixels,int width,int height,int num,int a, int c);
		void AddChar(BYTE *pAAPix,int w, int h,int nChar,int a, int c);

		bool BuildTextures();
		void CleanTextures();
		void CleanTempData();

	public:
		Font(char *szFaceName,int iHeight,bool bItalic,int iWeight,bool bAntiAlias,bool bMinimizeTextureSize=false);
		Font(const char *szFullPath,bool &bSuccess);		
		~Font();
		bool Save(HFILE hFile);
		void Shorten(); // removes a single row of pixels at the top of each character
		void ShortenFromBottom(); // removes a single row of pixels at the top of each character
		int GetTextureCount() { return iNumTextures;}
		void DrawTexture(HDC hDC, int iTexture, int x, int y);
		BYTE *GetCharMap(int iChar);
		void SetCharMap(int iChar,BYTE *pData);
		char *FaceName() {return header.szFaceName;}
		int PointSize() {return header.iSize;}
		bool IsItalic() {return header.bItalic;}
		bool IsBold() {return header.iWeight > 400;}

		int GetCharHeight(int iChar) {return (int)header.dwFontHeight;}
		int GetCharWidth(int iChar) {return header.bW[iChar];}
		int GetCharAWidth(int iChar) {return header.cA[iChar];}
		void  SetCharAWidth(int iChar,int iVal) {header.cA[iChar] = (signed char)iVal;}
		int GetCharCWidth(int iChar) {return header.cC[iChar];}
		void SetCharCWidth(int iChar,int iVal) {header.cC[iChar] = (signed char)iVal;}

		void ExportTGAS(const char *szTag,const char *szOutputDir);
		void ImportTGAS(const char *szFirstFile);
};

