// Font.cpp: implementation of the CFont class.
//
//////////////////////////////////////////////////////////////////////

#include "Font.h"

#include "OpenGL.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CFont::CFont()
{
	m_pszClassName = "CFont";

	///////////////////////////////////////////////////////////////////////////
	m_pSurface = NULL;

	m_pBMInfo = NULL;
	m_hBitmap = NULL;

	m_hFont = NULL;
	m_hMemDC = NULL;

	m_nName = 0;
}

CFont::~CFont()
{
	Destroy();
}

void CFont::Destroy()
{
	if (m_hBitmap)
	{
		DeleteObject(m_hBitmap);
		m_hBitmap = NULL;
	}
	if (m_pBMInfo)
	{
		delete m_pBMInfo;
		m_pBMInfo = NULL;
	}

	if (m_hMemDC)
	{
		DeleteDC(m_hMemDC);
		m_hMemDC = NULL;
	}

	if (m_hFont)
	{
		DeleteObject(m_hFont);
		m_hFont = NULL;
	}

	if (m_nName)
	{
		glDeleteTextures(1, &m_nName);
		m_nName = 0;
	}

	CUnknown::Destroy();
}

bool CFont::Create(LPSTR lpszFontName, DWORD dwHeight)
{
	if (!CUnknown::Create(lpszFontName))
		return false;

	///////////////////////////////////////////////////////////////////////////
	m_dwWidth  = iMAX_TEXTURE_SIZE;
	m_dwHeight = dwHeight;

	m_pBMInfo = new BITMAPINFO;
	if (!m_pBMInfo)
		return false;

	LPBITMAPINFOHEADER pBMIHeader = (LPBITMAPINFOHEADER) m_pBMInfo;
	ZeroMemory(pBMIHeader, sizeof(BITMAPINFOHEADER));

    pBMIHeader->biSize			= sizeof(BITMAPINFOHEADER);
    pBMIHeader->biWidth			=  (int) m_dwWidth;
    pBMIHeader->biHeight		= -(int) m_dwHeight;
    pBMIHeader->biPlanes		= 1;
    pBMIHeader->biBitCount		= 32;
	pBMIHeader->biCompression	= BI_RGB;

	m_hBitmap = CreateDIBSection(NULL, (LPBITMAPINFO) pBMIHeader, DIB_RGB_COLORS, (LPVOID*) &m_pSurface, NULL, 0);
	if (!m_hBitmap)
		return false;

	///////////////////////////////////////////////////////////////////////////
	m_hMemDC = CreateCompatibleDC(NULL);
	SetMapMode(m_hMemDC, MM_TEXT);

    // Create a font.  By specifying ANTIALIASED_QUALITY, we might get an
    // antialiased font, but this is not guaranteed.
    m_hFont = CreateFont(m_dwHeight, 0, 0, 0, FW_NORMAL, FALSE,
                         FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                         CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
                         VARIABLE_PITCH, lpszFontName);
    if (!m_hFont)
        return false;

	SelectObject(m_hMemDC, m_hBitmap);
    SelectObject(m_hMemDC, m_hFont);

	SetBkMode(m_hMemDC, OPAQUE);
	SetBkColor(m_hMemDC, RGB(0, 0, 0));
    SetTextAlign(m_hMemDC, TA_TOP);
	///////////////////////////////////////////////////////////////////////////

	// Create the texture
	glGenTextures(1, &m_nName);
	glBindTexture(GL_TEXTURE_2D, m_nName);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

	// nearest filter
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	return true;
}

void CFont::TextOutXY(int x, int y, LPSTR lpszText)
{
	// Draw some text on the Working surface
	ZeroMemory(m_pSurface, m_dwWidth * m_dwHeight * sizeof(DWORD));
	
	TextOut(m_hMemDC, 0, 0, lpszText, strlen(lpszText));
	
	// Apply Texture
	glBindTexture(GL_TEXTURE_2D, m_nName);

	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	glTexImage2D(GL_TEXTURE_2D, 
		         0, GL_RGBA, m_dwWidth, m_dwHeight, 
				 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pSurface);

	glBegin(GL_QUADS);

		// Upper left.
		glTexCoord2f(0, 0);
		glVertex2f((GLfloat) x, (GLfloat) y);

		// Lower right.
		glTexCoord2f(1, 0);
		glVertex2f((GLfloat) (x + m_dwWidth), (GLfloat) y);

		// Upper right.
		glTexCoord2f(1, 1);
		glVertex2f((GLfloat) (x + m_dwWidth), (GLfloat) (y + m_dwHeight));

		// Lower left.
		glTexCoord2f(0, 1);
		glVertex2f((GLfloat) x, (GLfloat) (y + m_dwHeight));

	glEnd();
}

void CFont::SetColor(DWORD dwColor)
{
	SetTextColor(m_hMemDC, dwColor);
}

void CFont::TextOutXY(int x, int y, LPSTR lpszText, DWORD dwColor)
{
	SetColor(dwColor);
	TextOutXY(x, y, lpszText);
}