/** 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/sgx/graphics/gfx_font.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/graphics/graphics.hpp"

CSGXFont::CSGXFont() :
m_LineSpacing(0),
m_CharacterSpacing(1) {
}

void 
CSGXFont::draw(CSGXDrawSurface *pSurface, const tCHAR c, const tPOINT x, const tPOINT y) const
{
	const tCHAR s[2] = { c, '\0' };
	draw(pSurface, s, x, y);
}

void 
CSGXFont::draw(CSGXDrawSurface *pSurface, const tCHAR *pStr, const tPOINT x, const tPOINT y) const
{
	draw(pSurface, pStr, x, y, CSGXFontFormatting());
}

void 
CSGXFont::draw(CSGXDrawSurface *pSurface, const tCHAR *pStr, const tPOINT x, const tPOINT y, const CSGXFontFormatting &formatting) const
{
	sgxVector<sgxString> stringList;

	if (formatting.m_bForceToRenderArea) {
		tUINT32 stringLength = getStringWidth(pStr);
		tUINT32 viewWidth = formatting.m_RenderArea.right - formatting.m_RenderArea.left;
		const tCHAR *pCurrString = pStr;
		const tCHAR *pNextString;

		while (stringLength > viewWidth) {
			sgxString s, last;

			// Skip leading whitespace
			while (sgxIsSpace(*pCurrString)) {
				++pCurrString;
			}
			pNextString = pCurrString;

			// Find the longest string
			// (either up to last space, or to last char before viewWidth hit)
			s = *pCurrString++;
			while(getStringWidth((const tCHAR *)s.c_str()) < viewWidth) {
				const tCHAR &c = *pCurrString++;
				if (sgxIsSpace(c)) {
					last = s;
				} else if (c == '\0') {
					break;
				}
				s += c;
			}
			//
			if (last == "") {
				// use the whole string, as there's no gaps in it!?!?!
				stringList.push_back(s);
				pCurrString = pNextString + s.length();
			} else {
				stringList.push_back(last);
				pCurrString = pNextString + last.length();
			}
			stringLength = getStringWidth(pCurrString);
		}

		if (*pCurrString) {	// there's text left, so add the remainder to the list
			stringList.push_back((char *)pCurrString);
		}
		
	} else {	
		// no block formatting required, so add the single string
		// into the list, to use the common render code.
		stringList.push_back((char *)pStr);
	}
	//
	tPOINT jy = y;
	tPOINT blockHeight = (stringList.size()-1) * (getHeight()+getLineSpacing());

	switch(formatting.m_iVertical) {
		case CSGXFontFormatting::fmtTopAlignment:
			break;
		case CSGXFontFormatting::fmtMiddleAlignment:
			jy -= (getHeight()+blockHeight) / 2;
			break;
		case CSGXFontFormatting::fmtBottomAlignment:
			jy -= blockHeight + getHeight();
			break;
		case CSGXFontFormatting::fmtMiddleXHeightAlignment:
			jy -= getXHeight()/2 + getAscender();
			break;
		case CSGXFontFormatting::fmtOnBaselineAlignment:
			jy -= getBaseline();
			break;
	}

	sgxVector<sgxString>::iterator it = stringList.begin();
	for(;it!=stringList.end();++it) {
		tPOINT jx = x;
		const tCHAR *pThisLine = (const tCHAR *)(*it).c_str();
		//
		switch(formatting.m_iHorizontal) {
			case CSGXFontFormatting::fmtLeftJustify:
				break;
			case CSGXFontFormatting::fmtCentreJustify:
				jx -= getStringWidth(pThisLine)/2;
				break;
			case CSGXFontFormatting::fmtRightJustify:
				jx -= getStringWidth(pThisLine);
				break;
		}
		//
		draw(pSurface, pThisLine, jx, jy);
		jy += getHeight();
		jy += getLineSpacing();
	}

}


tUINT32 
CSGXFont::getCharacterSpacing() const {
	return m_CharacterSpacing;
}

tUINT32 
CSGXFont::getLineSpacing() const {
	return m_LineSpacing;
}


tUINT32 CSGXFont::setCharacterSpacing(const tUINT32 spacing) {
tUINT32 prev = m_CharacterSpacing;
	m_CharacterSpacing = spacing;
	return prev;
}


tUINT32 CSGXFont::setLineSpacing(const tUINT32 spacing) {
tUINT32 prev = m_LineSpacing;
	m_LineSpacing = spacing;
	return prev;
}

tUINT32 
CSGXFont::getCharacterWidth(const tCHAR c) const {
	SGX_UNUSED(c);
	return 0;
}

tUINT32 
CSGXFont::getBaseline() const {
	return 0;
}

tUINT32 
CSGXFont::getXHeight() const {
	return 0;
}

tUINT32 
CSGXFont::getAscender() const {
	return 0;
}

tUINT32 
CSGXFont::getStringWidth(const tCHAR *pStr) const {
const tCHAR *p = pStr;
tUINT32 w;

	w = getCharacterWidth(*p);
	while(*++p) {
		w += m_CharacterSpacing + getCharacterWidth(*p);
	}
	
	return w;
}

tUINT32 
CSGXFont::getHeight() const {
	return 0;
}



