﻿#include "stdafx.h"
#include "UIFontData.h"

	/////////////////////////////////////////////////////
	//  --- -- --- THIS FILE IS IN UNICODE  --- -- --- //
	/////////////////////////////////////////////////////

SFontData SFontData::Mojangles_7
	= {

		/* Font Name */		"Mojangles7",

		/* Filename */		L"/TitleUpdate/res/font/Mojangles_7.png",

		/* Glyph count */	FONTSIZE,
		/* Codepoints */	SFontData::Codepoints,

		/*img wdth,hght*/	190, 264,
		/*img cols,rows*/	FONTCOLS, FONTROWS,


		/*glyph dim x,y*/	8,13,

		/*ascent/descent*/	7.f/13.f, 8.f/13.f,

		/*advance*/			1.f/10.f,

		/*whitespace*/		5,

	};


SFontData SFontData::Mojangles_11
	= {

		/* Font Name */		"Mojangles11",

		/* Filename */		L"/TitleUpdate/res/font/Mojangles_11.png",

		/* Glyph count */	FONTSIZE,
		/* Codepoints */	SFontData::Codepoints,

		/*img wdth,hght*/	305, 348,
		/*img cols,rows*/	FONTCOLS, FONTROWS,

		/*glyph dim x,y*/	13,17,	

		/*ascent/descent*/	11.f/17.f, 6.f/17.f,

		/*advance*/			1.f/13.f,

		/*whitespace*/		7

	};


  // -----------------------------------------------------------------------------
  // 4J-JEV: Glyph -> Unicode Maps,
  // Unicode search tool: http://www.fileformat.info/info/unicode/char/search.htm
  //------------------------------------------------------------------------------


// Originally interpretted from 'Chars.txt', required many alterations to work correctly. (New Characters have been also added)
unsigned short SFontData::Codepoints[FONTSIZE] =
{
	// NOTE: When adding characters here, you may also want to add them to the ignore list 'Mojangles\Dev\Tools\Mojangles.txt' so we know not to panic when localisation uses them.

/*			ż		Ż		ź		Ź		ć		Ć		ń		Ń																													*/
	0x0001,	0x017C,	0x017B,	0x017A,	0x0179,	0x0107,	0x0106,	0x0144,	0x0143,	0x000A,	0x000B,	0x000C,	0x000D,	0x000E,	0x000F,	0x0010,	0x0011,	0x0012,	0x0013,	0x0014,	0x0015,	0x0016,	0x0017,

/*																					!		"		#		$		%		&		'		(		)		*		+		,		-	*/
	0x0018,	0x0019,	0x001A,	0x001B,	0x001C,	0x001D,	0x001E,	0x001F,	0x0020,	0x0000,	0x0021,	0x0022,	0x0023,	0x0024,	0x0025,	0x0026,	0x0027,	0x0028,	0x0029,	0x002A,	0x002B,	0x002C,	0x002D,

/*	.		/		0		1		2		3		4		5		6		7		8		9		:		;		<		=		>		?		@		A		B		C		D	*/
	0x002E,	0x002F,	0x0030,	0x0031,	0x0032,	0x0033,	0x0034,	0x0035,	0x0036,	0x0037,	0x0038,	0x0039,	0x003A,	0x003B,	0x003C,	0x003D,	0x003E,	0x003F,	0x0040,	0x0041,	0x0042,	0x0043,	0x0044,

/*	E		F		G		H		I		J		K		L		M		N		O		P		Q		R		S		T		U		V		W		X		Y		Z		[	*/
	0x0045,	0x0046,	0x0047,	0x0048,	0x0049,	0x004A,	0x004B,	0x004C,	0x004D,	0x004E,	0x004F,	0x0050,	0x0051,	0x0052,	0x0053,	0x0054,	0x0055,	0x0056,	0x0057,	0x0058,	0x0059,	0x005A,	0x005B,

/*	\		]		^		_		`		a		b		c		d		e		f		g		h		i		j		k		l		m		n		o		p		q		r	*/
	0x005C,	0x005D,	0x005E,	0x005F,	0x0060,	0x0061,	0x0062,	0x0063,	0x0064,	0x0065,	0x0066,	0x0067,	0x0068,	0x0069,	0x006A,	0x006B,	0x006C,	0x006D,	0x006E,	0x006F,	0x0070,	0x0071,	0x0072,

/*	s		t		u		v		w		x		y		z		{		|		}		~																							*/
	0x0073,	0x0074,	0x0075,	0x0076,	0x0077,	0x0078,	0x0079,	0x007A,	0x007B,	0x007C,	0x007D,	0x007E,	0x007F,	0x0080,	0x0081,	0x0082,	0x0083,	0x0084,	0x0085,	0x0086,	0x0087,	0x0088,	0x0089,

/*																																														*/
	0x008A,	0x008B,	0x008C,	0x008D,	0x008E,	0x008F,	0x0090,	0x0091,	0x0092,	0x0093,	0x0094,	0x0095,	0x0096,	0x0097,	0x0098,	0x0099,	0x009A,	0x009B,	0x009C,	0x009D,	0x009E,	0x009F,	0x00A0,

/*	¡		¢		£		¤		¥		¦		§		¨		©		ª		«		¬		­		®		¯		°		±		²		³		´		µ		¶		·	*/
	0x00A1,	0x00A2,	0x00A3,	0x00A4,	0x00A5,	0x00A6,	0x00A7,	0x00A8,	0x00A9,	0x00AA,	0x00AB,	0x00AC,	0x00AD,	0x00AE,	0x00AF,	0x00B0,	0x00B1,	0x00B2,	0x00B3,	0x00B4,	0x00B5,	0x00B6,	0x00B7,

/*	¸		¹		º		»		¼		½		¾		¿		À		Á		Â		Ã		Ä		Å		Æ		Ç		È		É		Ê		Ë		Ì		Í		Î	*/
	0x00B8,	0x00B9,	0x00BA,	0x00BB,	0x00BC,	0x00BD,	0x00BE,	0x00BF,	0x00C0,	0x00C1,	0x00C2,	0x00C3,	0x00C4,	0x00C5,	0x00C6,	0x00C7,	0x00C8,	0x00C9,	0x00CA,	0x00CB,	0x00CC,	0x00CD,	0x00CE,

/*	Ï		Ð		Ñ		Ò		Ó		Ô		Õ		Ö		×		Ø		Ù		Ú		Û		Ü		Ý		Þ		ß		à		á		â		ã		ä		å	*/
	0x00CF,	0x00D0,	0x00D1,	0x00D2,	0x00D3,	0x00D4,	0x00D5,	0x00D6,	0x00D7,	0x00D8,	0x00D9,	0x00DA,	0x00DB,	0x00DC,	0x00DD,	0x00DE,	0x00DF,	0x00E0,	0x00E1,	0x00E2,	0x00E3,	0x00E4,	0x00E5,

/*	æ		ç		è		é		ê		ë		ì		í		î		ï		ð		ñ		ò		ó		ô		õ		ö		÷		ø		ù		ú		û		ü	*/
	0x00E6,	0x00E7,	0x00E8,	0x00E9,	0x00EA,	0x00EB,	0x00EC,	0x00ED,	0x00EE,	0x00EF,	0x00F0,	0x00F1,	0x00F2,	0x00F3,	0x00F4,	0x00F5,	0x00F6,	0x00F7,	0x00F8,	0x00F9,	0x00FA,	0x00FB,	0x00FC,

/*	ý		þ		ÿ		Œ		œ		Š		š		Ÿ		Ž		ž		ƒ		ˣ		➄		–		—		’		‚		“		”		„		†		‡		•	*/
	0x00FD,	0x00FE,	0x00FF,	0x0152,	0x0153,	0x0160,	0x0161,	0x0178,	0x017D,	0x017E,	0x0192,	0x02E3,	0x2784,	0x2013,	0x2014,	0x2019,	0x201A,	0x201C,	0x201D,	0x201E,	0x2020,	0x2021,	0x2022,

/*	…		‰		‹		›		€		™		͝		Ş		İ		Ğ		ş		ı		ğ		ę		Ę		ó		Ó		ą		Ą		ś		Ś		ł		Ł	*/
	0x2026,	0x2030,	0x2039,	0x203A,	0x20AC,	0x2122,	0x035D,	0x015E,	0x0130,	0x011E,	0x015F,	0x0131,	0x011F,	0x0119,	0x0118,	0x00F3,	0x00D3,	0x0105,	0x0104,	0x015B,	0x015A,	0x0142,	0x0141,

/*	Ё		А		Б		В		Г		Д		Е		Ж		З		И		Й		К		Л		М		Н		О		П		Р		С		Т		У		Ф		Х	*/
	0x0401,	0x0410,	0x0411,	0x0412,	0x0413,	0x0414,	0x0415,	0x0416,	0x0417,	0x0418,	0x0419,	0x041A,	0x041B,	0x041C,	0x041D,	0x041E,	0x041F,	0x0420,	0x0421,	0x0422,	0x0423,	0x0424,	0x0425,

/*	Ц		Ч		Ш		Щ		Ъ		Ы		Ь		Э		Ю		Я		а		б		в		г		д		е		ж		з		и		й		к		л		м	*/
	0x0426,	0x0427,	0x0428,	0x0429,	0x042A,	0x042B,	0x042C,	0x042D,	0x042E,	0x042F,	0x0430,	0x0431,	0x0432,	0x0433,	0x0434,	0x0435,	0x0436,	0x0437,	0x0438,	0x0439,	0x043A,	0x043B,	0x043C,

/*	н		о		п		р		с		т		у		ф		х		ц		ч		ш		щ		ъ		ы		ь		э		ю		я		ё		χ		ψ		ω	*/
	0x043D,	0x043E,	0x043F,	0x0440,	0x0441,	0x0442,	0x0443,	0x0444,	0x0445,	0x0446,	0x0447,	0x0448,	0x0449,	0x044A,	0x044B,	0x044C,	0x044D,	0x044E,	0x044F,	0x0451,	0x03C7,	0x03C8,	0x03C9,

/*	Č		Ď		Ě		Ĺ		Ľ		Ň		Ő		Ř		Ť		Ů		Ű		č		ď		ě		ĺ		ľ		ň		ő		ř		ť		ů		ű		 	*/
	0x010C,	0x010E,	0x011A,	0x0139,	0x013D,	0x0147,	0x0150,	0x0158,	0x0164,	0x016E,	0x0170,	0x010D,	0x010F,	0x011B,	0x013A,	0x013E,	0x0148,	0x0151,	0x0159,	0x0165,	0x016F,	0x0171,	0x0020,

/*	Α		Β		Γ		Δ		Ε		Ζ		Η		Θ		Ι		Κ		Λ		Μ		Ν		Ξ		Ο		Π		Ρ		Σ		Τ		Υ		Φ		Χ		Ψ	*/
	0x0391,	0x0392,	0x0393,	0x0394,	0x0395,	0x0396,	0x0397,	0x0398,	0x0399,	0x039A,	0x039B,	0x039C,	0x039D,	0x039E,	0x039F,	0x03A0,	0x03A1,	0x03A3,	0x03A4,	0x03A5,	0x03A6,	0x03A7,	0x03A8,

/*	Ω		α		β		γ		δ		ε		ζ		η		θ		ι		κ		λ		μ		ν		ξ		ο		π		ρ		ς		σ		τ		υ		φ	*/
	0x03A9,	0x03B1,	0x03B2,	0x03B3,	0x03B4,	0x03B5,	0x03B6,	0x03B7,	0x03B8,	0x03B9,	0x03BA,	0x03BB,	0x03BC,	0x03BD,	0x03BE,	0x03BF,	0x03C0,	0x03C1,	0x03C2,	0x03C3,	0x03C4,	0x03C5,	0x03C6,

/*	Ά		Έ		Ή		Ί		Ό		Ύ		Ώ		ΐ		ά		έ		ή		ί		ϊ		ό		ύ		ώ		ŕ		΄		‘									*/
	0x0386,	0x0388,	0x0389,	0x038A,	0x038C,	0x038E,	0x038F,	0x0390,	0x03AC,	0x03AD,	0x03AE,	0x03AF,	0x03CA,	0x03CC,	0x03CD,	0x03CE,	0x0155,	0x0384,	0x2018,	0x0000,	0x0000,	0x0000,	0x0000,
};




	     ///////////////////////
		// --- CFontData --- //
	   ///////////////////////

CFontData::CFontData()
{
	m_unicodeMap = unordered_map<unsigned int, unsigned short>();

	m_sFontData = NULL;
	m_kerningTable = NULL;
	m_pbRawImage = NULL;
}

CFontData::CFontData(SFontData &sFontData, int *pbRawImage)
	: m_unicodeMap( sFontData.m_uiGlyphCount + 2 )
{
	this->m_sFontData = &sFontData;

	// INITIALISE ALPHA CHANNEL //

	// Glyph Archive (1Byte per pixel).
	unsigned int archiveSize = sFontData.m_uiGlyphMapX * sFontData.m_uiGlyphMapY; 
	
	this->m_pbRawImage = new unsigned char[archiveSize];

	// 4J-JEV: Take the alpha channel from each pixel.
	for (unsigned int i = 0; i < archiveSize; i++)
	{
		this->m_pbRawImage[i] = (pbRawImage[i] & 0xFF000000) >> 24;
	}

	// CREATE UNICODE MAP //
	for (unsigned int i = 0; i < sFontData.m_uiGlyphCount; i++)
	{
		unordered_map<unsigned int, unsigned short>::value_type pair(sFontData.Codepoints[i], i);
		m_unicodeMap.insert( pair );
	}

	// CREATE KERNING TABLE //
	m_kerningTable = new unsigned short[sFontData.m_uiGlyphCount];
	for (unsigned short glyph = 0; glyph < sFontData.m_uiGlyphCount; glyph++)
	{
		int row,column;
		getPos(glyph,row,column);

		short xMax = 0, _x=0, _y=0;

		// Find the position of the topLeft corner.
		unsigned char *topLeft = m_pbRawImage, *cursor;
		moveCursor(	topLeft, column * sFontData.m_uiGlyphWidth, row * sFontData.m_uiGlyphHeight);

		assert( ((column+1)*sFontData.m_uiGlyphWidth) < sFontData.m_uiGlyphMapX );
		assert( ((row+1)*sFontData.m_uiGlyphHeight) < sFontData.m_uiGlyphMapY );

		static int XX = 79;
		// Find the furthest filled pixel to the right.
		for (short y = 0; y < sFontData.m_uiGlyphHeight; y++)
		{
			for (short x = 0; x < sFontData.m_uiGlyphWidth; x++)
			{
				cursor = topLeft;
				moveCursor(cursor, x, y);
				
				assert( (cursor-m_pbRawImage) < archiveSize );

				if ( *cursor > 0 )
				{
					if (x > xMax) xMax = x;
					_x = x;
					_y = y;
				}
			}
		}

#if _DEBUG_BLOCK_CHARS
		for (short y = 0; y < sFontData.m_uiGlyphHeight; y++)
		{
			for (short x = 0; x < sFontData.m_uiGlyphWidth; x++)
			{
				cursor = topLeft;
				moveCursor(cursor, x, y);

				if (x==0)			*cursor = 0x00;
				else if (x<=xMax)	*cursor = 0xFF;
				else				*cursor = 0x00;
			}
		}
#endif

		// 4J-JEV: Empty glyphs are considered to be whitespace.
		if (xMax == 0)	m_kerningTable[glyph] = sFontData.m_uiWhitespaceWidth;
		else			m_kerningTable[glyph] = xMax + 1;
	}

	// CACHE GLYPH ADVANCES //
	m_pfAdvanceTable = new float[sFontData.m_uiGlyphCount];
	for (unsigned short glyph = 0; glyph < sFontData.m_uiGlyphCount; glyph++)
	{
		m_pfAdvanceTable[glyph] = m_kerningTable[glyph] * m_sFontData->m_fAdvPerPixel;
	}

	// DEBUG //
#ifndef _CONTENT_PACKAGE
	for (int i = 0; i < sFontData.m_uiGlyphCount; i++)
	{
		int unicode = getUnicode(i), unicodeChar = 32, row, col;
		if ( 32 < unicode && unicode < 127 && unicode != 0x0025 )
		{
			unicodeChar = unicode;
		}

		getPos(i, row, col);

		string state = "ok";
		if (i != getGlyphId(unicode))
		{
			state = "MISSMATCHED!";

			app.DebugPrintf( "<GLYPH_%03i> %i\t%c\tU+%.4X, kerning=%i, (%2i,%2i). %s\n", 
				i, getGlyphId(unicode), unicodeChar, unicode, m_kerningTable[i], row, col, state.c_str() );
		}
	}
#endif
}

void CFontData::release()
{
	delete [] m_kerningTable;
	delete [] m_pfAdvanceTable;
	delete [] m_pbRawImage;
}

const string CFontData::getFontName()
{
	return m_sFontData->m_strFontName;
}

SFontData *CFontData::getFontData()
{
	return m_sFontData;
}

unsigned short CFontData::getGlyphId(unsigned int unicodepoint)
{
	unordered_map<unsigned int, unsigned short>::iterator out = m_unicodeMap.find(unicodepoint);
	if (out != m_unicodeMap.end())
		return out->second;
	return 0;
}

unsigned int CFontData::getUnicode(unsigned short glyphId)
{
	return m_sFontData->Codepoints[glyphId];
}

unsigned char *CFontData::topLeftPixel(int row, int col)
{
	unsigned char *out = m_pbRawImage;
	moveCursor(out, col * m_sFontData->m_uiGlyphWidth, row* m_sFontData->m_uiGlyphHeight);
	return out;
}

void CFontData::getPos(unsigned short glyphId, int &rowOut, int &colOut)
{
	rowOut = glyphId / m_sFontData->m_uiGlyphMapCols;
	colOut = glyphId % m_sFontData->m_uiGlyphMapCols;
}

float CFontData::getAdvance(unsigned short glyphId)
{
	return m_pfAdvanceTable[glyphId];
}

int CFontData::getWidth(unsigned short glyphId)
{
	return m_kerningTable[glyphId];
}

bool CFontData::glyphIsWhitespace(unsigned short glyphId)
{
	return unicodeIsWhitespace( getUnicode(glyphId) );
}

bool CFontData::unicodeIsWhitespace(unsigned int unicode)
{
	static const unsigned int MAX_WHITESPACE = 1;
	static const unsigned int whitespace[MAX_WHITESPACE] = { 
		0x0020 
	};

	for (int i=0; i<MAX_WHITESPACE; i++)
	{
		if (unicode == whitespace[i])	return true;
	}

	return false;
}

void CFontData::moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy)
{
	cursor += (dy * m_sFontData->m_uiGlyphMapX) + dx;
}
