/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/drivers/common/ftgl/ftgl_font_manager.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/graphics/graphics.hpp"
#include "sgx/filesystem/filesystem.hpp"
#include "drivers/common/ftgl/ftgl_font_manager.hpp"
#include "lib/FTlibrary.h"
#include "lib/FTGLExtrdFont.h"
#include "lib/FTGLOutlineFont.h"
#include "lib/FTGLPolygonFont.h"
#include "lib/FTGLTextureFont.h"
#include "lib/FTGLPixmapFont.h"
#include "lib/FTGLBitmapFont.h"

class CDeviceFTGLFont : public CSGXFont {
public:
	virtual void draw(CSGXDrawSurface *pSurface, const tCHAR *pStr, const tPOINT x, const tPOINT y) const;
	virtual tUINT32 getHeight() const;

	virtual tUINT32 getBaseline() const;
	virtual tUINT32 getXHeight() const;
	virtual tUINT32 getAscender() const;
	virtual tUINT32 getStringWidth(const sgxString &str) const;
	virtual tUINT32 getCharacterWidth(const tCHAR c) const;

	FTFont	*m_pFTFont;
};

CSGXFontManager *CDeviceFTGLFontManager::create()
{
	m_pSingleton = new CDeviceFTGLFontManager();
	if (m_pSingleton) {
		m_pSingleton->initialize();
	}
	return m_pSingleton;
}

CSGXFontManager *CDeviceFTGLFontManager::get()
{
	if (!m_pSingleton) {
		return create();
	}
	return m_pSingleton;
}

CDeviceFTGLFontManager::CDeviceFTGLFontManager() : CSGXFontManager()
{
}

CDeviceFTGLFontManager::~CDeviceFTGLFontManager()
{
}

void
CDeviceFTGLFontManager::initialize()
{
}

CSGXFont *	
CDeviceFTGLFontManager::registerFont(const sgxString &name, const sgxString &filename, const CSGXFontParams &params)
{
	CSGXFont *pBaseFont = CSGXFontManager::registerFont(name, filename, params);
	if (pBaseFont) {
		return pBaseFont;
	}

	FTFont *pFT;
	sgxString full(filename);
	full += ".dat";
	sgxString native = CSGXFileSystem::get()->getNativePath(full);

	switch(params.m_iFontType) {
	case	CSGXFontParams::eBitmapFontType:
		pFT = new FTGLBitmapFont(native.c_str());
		break;

	case	CSGXFontParams::eOutlineFontType:
		pFT = new FTGLOutlineFont(native.c_str());
		break;

	case	CSGXFontParams::ePolygonFontType:
		pFT = new FTGLPolygonFont(native.c_str());
		break;

	case	CSGXFontParams::eExtrudedFontType:
		pFT = new FTGLExtrdFont(native.c_str());
		break;

	case	CSGXFontParams::ePixmapFontType:
		pFT = new FTGLPixmapFont(native.c_str());
		break;

	case	CSGXFontParams::eTextureFontType:
		pFT = new FTGLTextureFont(native.c_str());
		break;

	default:
		return NULL;
	}

	if (pFT && !pFT->Error()) {
		
		pFT->FaceSize(params.m_iTypeSize);
		pFT->Depth((tREAL32)params.m_iTypeDepth);
		pFT->CharMap(ft_encoding_unicode);

		CDeviceFTGLFont *pFont = new CDeviceFTGLFont;
		if (!pFont) {
			delete pFT;
			return NULL;
		}

		pFont->m_pFTFont = pFT;

		return CSGXFontManager::registerFont(name, pFont);
	}
	return NULL;
}

void 
CDeviceFTGLFont::draw(CSGXDrawSurface *pSurface, const tCHAR *pStr, const tPOINT x, const tPOINT y) const
{
	sgxColorRGBA col;
	
	CSGXGraphicsEngine::get()->getColor(col);

	glColor4f(col.r, col.g, col.b, col.a);
	glRasterPos2i(x, y + getHeight());	// FTGL font's consider the y as baseline

	m_pFTFont->Render((const char *)pStr);
}

tUINT32 
CDeviceFTGLFont::getBaseline() const {
	tUINT32 h = m_pFTFont->FaceSize();
	
	h-= (tUINT32)m_pFTFont->Descender();
	return h;
}

tUINT32 
CDeviceFTGLFont::getXHeight() const {
	tUINT32 xh;
	
	xh = (tUINT32)m_pFTFont->Ascender()+ getAscender();
	xh += (tUINT32)m_pFTFont->Descender();
	return xh;
}

tUINT32 
CDeviceFTGLFont::getAscender() const {
	return m_pFTFont->FaceSize() - (tUINT32)m_pFTFont->Ascender();;
}

tUINT32 
CDeviceFTGLFont::getCharacterWidth(const tCHAR c) const {
	char s[] = { c, 0};
	return (tUINT32) m_pFTFont->Advance(s);
}

tUINT32 
CDeviceFTGLFont::getStringWidth(const sgxString &str) const {
	return (tUINT32) m_pFTFont->Advance(str.c_str());
}

tUINT32 
CDeviceFTGLFont::getHeight() const {
	return m_pFTFont->FaceSize();
}
