/// Copyright (c) 2009 Ruben Penalva. All rights reserved.
/// Redistribution and use in source and binary forms, with or without modification, 
/// are permitted provided that the following conditions are met:
///    1. Redistributions of source code must retain the above copyright notice, this 
///    list of conditions and the following disclaimer.
///    2. Redistributions in binary form must reproduce the above copyright notice,
///    this list of conditions and the following disclaimer in the documentation and/or
///    other materials provided with the distribution.
///    3. The name of the author may not be used to endorse or promote products derived
///    from this software without specific prior written permission.
///
/// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
/// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
/// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 
/// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
/// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
/// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
/// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// @file GlyphOutlineLoader.cpp
/// This source file is part of LetterCDT test.
/// The file holds the GlyphOutlineLoader class interface.
/// @author Ruben Penalva (ruben.penalva@rpenalva.com)
#include "GlyphOutlineLoader.h"

#include "UnicodeString.h"
#include "GlyphOutline.h"

using namespace LetterCDT;

GlyphOutlineLoader::GlyphOutlineLoader(const std::wstring& fontFile)	:	m_library(0), m_face(0)
{
	LoadFontFace(fontFile);
}

GlyphOutlineLoader::~GlyphOutlineLoader(void)
{
	Destroy();
}

GlyphOutline* GlyphOutlineLoader::GetGlyphOutline(wchar_t charCode)
{
	std::map<wchar_t, GlyphOutline*>::iterator it = m_glyphOutlines.find(charCode);
	if (it != m_glyphOutlines.end())
	{
		return it->second;
	}
	
	GlyphOutline* glyphOutline = new GlyphOutline(charCode, m_face);
	m_glyphOutlines[charCode] = glyphOutline;
	
	return glyphOutline;
}

void GlyphOutlineLoader::LoadFontFace(const std::wstring& fontFile)
{
	FT_Error error = FT_Init_FreeType(&m_library); 
	if (error) 
	{
		throw std::wstring(L"[ERROR] Unable to initialize FTLibrary. Method: LoadFontFace.");
	} 

	const std::string utf8FontFile(ConvertUTF16ToUTF8(fontFile));

	error = FT_New_Face(m_library, utf8FontFile.c_str(), 0, &m_face ); 
	if (error == FT_Err_Unknown_File_Format) 
	{ 
		Destroy();

		throw std::wstring(L"[ERROR] the font file could be opened and read, but it appears that its font format is unsupported. Method: LoadFontFace.");
	} 
	else if (error) 
	{ 
		Destroy();

		throw std::wstring(L"[ERROR] another error code means that the font file could not be opened or read, or simply that it is broken. Method: LoadFontFace.");
	}   
	
	error = FT_Set_Char_Size(m_face, 0, 9 * 64, 70, 70);
	if (error)
	{
		Destroy();

		throw std::wstring(L"[ERROR] Unable to set character size. Method: LoadFontFace.");
	}
}

void GlyphOutlineLoader::Destroy(void)
{
	FT_Done_FreeType(m_library);
	FT_Done_Face(m_face);

	std::map<wchar_t, GlyphOutline*>::iterator it = m_glyphOutlines.begin();
	std::map<wchar_t, GlyphOutline*>::iterator itEnd = m_glyphOutlines.end();
	while (it != itEnd)
	{
		delete it->second;

		++it;
	}
}