/*
								+--------------------------------+
								|                                |
								|   ***  Bitmap font tool  ***   |
								|                                |
								|  Copyright © -tHE SWINe- 2010  |
								|                                |
								|         FontTexture2.h         |
								|                                |
								+--------------------------------+
*/

#pragma once
#ifndef __FONT_TEXTURE_INCLUDED
#define __FONT_TEXTURE_INCLUDED

/**
 *	@file FontTexture2.h
 *	@author -tHE SWINe-
 *	@brief a simple bitmap font texture creation tool
 *	@date 2010
 *
 *	@date 2014-03-12
 *
 *	Clarified how CBitmapFont::Request_UnicodeBlock() works (it removes basic latin,
 *	that needs to be requested specifically).
 *
 *	Added __FONT_TEXTURE_WINDOWS_AUTOLOAD_FONTS_FROM_FILE, CBitmapFont::n_Load_FontFile()
 *	and CBitmapFont::Unload_FontFile() for creating fonts from files (.ttf, .otf, ...)
 *	without having to manually install them in the system (windows workarround).
 *
 *	Added the possiblity to specify the metadata block blanking color.
 *
 *	Improved documentation.
 */

#include "UniConv.h"
#include "StlUtils.h"
#include "Unused.h"
#include "BinPacking.h"
#include "Tga.h"

/**
 *	@def __FONT_TEXTURE_WINDOWS_AUTOLOAD_FONTS_FROM_FILE
 *	@brief If defined, the font loader attempts to load fonts from files.
 *		Note that this only works if the file exists and if it only contains a single font.
 */
#define __FONT_TEXTURE_WINDOWS_AUTOLOAD_FONTS_FROM_FILE

/**
 *	@brief basic bitmap font structures namespace
 */
namespace bitmapfont2 {

#pragma pack (1)

/**
 *	@brief information about the packaging system
 */
struct TContainerInfo {
	uint32_t n_container_width; /**< @brief container width, in pixels (buaranteed to be at least 4 pixels) */
	uint32_t n_container_height; /**< @brief container height, in pixels */
	uint32_t n_crc32; /**< @brief crc of the whole container block */
	uint32_t n_stream_id; /**< @brief stream id (must be the same in all the blocks) */
	uint32_t n_block_id; /**< @brief container 0 is immediately followed by TFontInfo record */
	uint32_t n_block_num; /**< @brief number of pages with container blocks (not number of pages in total!) */
	uint32_t n_page_info_num; /**< @brief number of the following TPageInfo structures */

	// [TFontInfo (if container 0)]
	// [TPageInfo 0]
	// [TPageInfo 1]
	//		.
	//		.
	// [TPageInfo n_page_info_num-1]
};

struct TPageInfo {
	uint32_t n_page_id; /**< @brief id of the page */
	uint32_t n_glyph_num; /**< @brief number of glyphs in this page (note a single page may be fragmented accross several containers) */

	// [TGlyphInfo 0]
	// [TGlyphInfo 1]
	//		.
	//		.
	// [TGlyphInfo n_glyph_num-1]
};

/**
 *	@brief source font information (this is used for packed storage)
 */
struct TFontInfo {
	uint16_t n_font_size; /**< @brief font size, in pixels */
	uint16_t n_font_weight; /**< @brief font weight (400 is regular, 800 is bold) */
	uint8_t b_italic; /**< @brief italic flag */
	uint8_t b_underline; /**< @brief underline flag */
	// font style

	uint16_t n_page_num; /**< @brief actual number of pages */
	uint16_t n_max_page_width; /**< @brief actual width of the largest page, in pixels */
	uint16_t n_max_page_height; /**< @brief actual height of the largest page, in pixels */
	uint16_t n_max_page_size; /**< @brief maximum dimension allowed in creation of the font */
	uint16_t n_page_padding; /**< @brief page padding, in pixels */
	uint16_t n_glyph_tex_padding; /**< @brief texture padding, in pixels (to support mip-mapping without the glyphs blending into each other) */
	uint16_t n_glyph_geom_padding; /**< @brief geometry padding, in pixels (to support mip-mapping without the rendered glyph quads having visible (opaque) edges) */
	// glyph packing parameters

	int16_t n_ascent; /**< @brief character ascent, in pixels */
	int16_t n_descent; /**< @brief character descent, in pixels (important) */
	int16_t n_height; /**< @brief character height, in pixels */
	int16_t n_int_leading; /**< @brief internal leading, in pixels (important) */
	int16_t n_ext_leading; /**< @brief external leading, in pixels */
	int16_t n_space_width; /**< @brief width of the space glyph (it is not stored as glyph info as it does not need a bitmap) */
	int16_t n_x_height; /**< @brief height of the 'x' glyph */
	int16_t n_newline_height; /**< @brief newline height (distance the caret must shift on newline; important), this equals <tt>n_height + n_ext_leading</tt> */
	// basic glyph metrics // @todo - fill these

	uint16_t n_extension_block_num; /**< @brief number of extension blocks */
	uint8_t n_font_face_length; /**< @brief length of font face name, in bytes (encoded as utf-8, terminating null not included / stored) */

	// [n_font_face_length bytes, utf-8, terminating null is not stored]
	// [TExtensionBlock 0]
	// [TExtensionBlock 1]
	//		.
	//		.
	// [TExtensionBlock n_extension_block_num-1]
};

/**
 *	@brief block with font info extension
 */
struct TExtensionBlock {
	uint16_t n_block_id; /**< @brief extension block id */
	uint8_t b_important; /**< @brief extension block importance (0 = can skip such blocks, 1 = need to decode the block in order to be able to correctly use the font) */
	uint32_t n_payload_size; /**< @brief extension block payload size (can be used to skip over blocks) */

	// [n_payload_size bytes follow]
};

/**
 *	@brief glyph rendering information (this is used for packed storage and also by the font rendering system)
 */
struct TGlyphInfo {
	int32_t n_code; /**< @brief utf-32 (0 - 0x10ffff) */

	int32_t n_baseline_offset_x; /**< @brief offset from baseline point to bottom-left bitmap corner */
	int32_t n_baseline_offset_y; /**< @brief offset from baseline point to bottom-left bitmap corner */
	int32_t n_caret_shift; /**< @brief width of glyph base (position shift for the next glyph) */

	uint8_t b_rotation; /**< @brief 90 degrees rotation flag (ccw rotation) */
	uint32_t n_bitmap_pos_x; /**< @brief origin in glyph atlas page */
	uint32_t n_bitmap_pos_y; /**< @brief origin in glyph atlas page */
	uint32_t n_bitmap_width; /**< @brief width of actual bitmap containing the glyph (without offset, rotation not taken into account) */
	uint32_t n_bitmap_height; /**< @brief height of actual bitmap containing the glyph (without offset, rotation not taken into account) */
};

#pragma pack()

/**
 *	@brief a simple manipulator class for TGlyphInfo to allow it's use with CBinPackingSolver
 */
class CBoxAdapter {
public:
	/**
	 *	@copydoc CBinPackingItemManipulator::n_X()
	 */
	static inline uint32_t n_X(const TGlyphInfo &r_t_item)
	{
		return r_t_item.n_bitmap_pos_x;
	}

	/**
	 *	@copydoc CBinPackingItemManipulator::n_Y()
	 */
	static inline uint32_t n_Y(const TGlyphInfo &r_t_item)
	{
		return r_t_item.n_bitmap_pos_y;
	}

	/**
	 *	@copydoc CBinPackingItemManipulator::n_Width()
	 */
	static inline uint32_t n_Width(const TGlyphInfo &r_t_item)
	{
		return (r_t_item.b_rotation)? r_t_item.n_bitmap_height : r_t_item.n_bitmap_width;
	}

	/**
	 *	@copydoc CBinPackingItemManipulator::n_Height()
	 */
	static inline uint32_t n_Height(const TGlyphInfo &r_t_item)
	{
		return (r_t_item.b_rotation)? r_t_item.n_bitmap_width : r_t_item.n_bitmap_height;
	}

	/**
	 *	@copydoc CBinPackingItemManipulator::Set_Position()
	 */
	static inline void Set_Position(TGlyphInfo &r_t_item, uint32_t n_x, uint32_t n_y)
	{
		r_t_item.n_bitmap_pos_x = n_x;
		r_t_item.n_bitmap_pos_y = n_y;
	}

	/**
	 *	@copydoc CBinPackingItemManipulator::b_CanTurn()
	 */
	static inline bool b_CanTurn(const TGlyphInfo &UNUSED(r_t_item))
	{
		return true;
	}

	/**
	 *	@copydoc CBinPackingItemManipulator::Turn()
	 */
	static inline void Turn(TGlyphInfo &r_t_item)
	{
		r_t_item.b_rotation = !r_t_item.b_rotation;
	}
};


/**
 *	@brief configuration of bin packing page for bitmap font
 */
typedef CBinPackingPage<uint32_t, TGlyphInfo, CBoxAdapter> CBitmapFontPage;

/**
 *	@brief configuration of bin packing solver for bitmap font
 */
typedef CBinPackingSolver<uint32_t, TGlyphInfo, CBoxAdapter> CBitmapFontBPSolver;

/**
 *	@brief metadata block writer class
 */
class CMetadataWriter;

/**
 *	@brief glyph renderer class (platform specific)
 */
class CGlyphRenderer;

}; // ~bitmapfont2

/**
 *	@brief a simple bitmap font with unicode support
 */
class CBitmapFont {
public:
	/**
	 *	@brief 2D rectangle
	 */
	struct TRectangle {
		size_t n_left; /**< @brief horizontal position of the left edge, in pixels */
		size_t n_top; /**< @brief vertical position of the top edge, in pixels */
		size_t n_width; /**< @brief width, in pixels */
		size_t n_height; /**< @brief height, in pixels */
	};

	/**
	 *	@brief bitmap output callback
	 *	@note I did this on purpose (doing it using templated function
	 *		parameter would result in some large template functions).
	 */
	class CBitmapCallback {
	public:
		/**
		 *	@brief font page callback
		 *
		 *	@param[in] n_page is zero-based index of the page
		 *	@param[in] n_page_num is number of pages
		 *	@param[in] r_t_bitmap is page bitmap (may contain metadata block)
		 *
		 *	@return Returns true on success, false on failure.
		 */
		virtual bool operator ()(size_t n_page, size_t n_page_num, const TBmp &r_t_bitmap) = 0;
	};

	/**
	 *	@brief bitmap writer callback
	 *	@note This is not useful for anything else than debugging.
	 *		A typical bitmap callback would build an OpenGL texture.
	 */
	class CBitmapWriter : public CBitmapCallback {
	protected:
		const char *m_p_s_format; /**< @brief format string with a single %d in it */
		std::string m_s_filename; /**< @brief storage for the actual filenames */

	public:
		/**
		 *	@brief default constructor
		 *	@param[in] p_s_format is filename with a single "%d" in it
		 */
		CBitmapWriter(const char *p_s_format)
			:m_p_s_format(p_s_format)
		{}

		/**
		 *	@copydoc CBitmapCallback::operator()()
		 */
		virtual bool operator ()(size_t n_page, size_t n_page_num, const TBmp &r_t_bitmap)
		{
			return stl_ut::Format(m_s_filename, m_p_s_format, n_page) &&
				CTgaCodec::Save_TGA(m_s_filename.c_str(), r_t_bitmap, true);
		}
	};

	/**
	 *	@brief an empty bitmap writer callback, which can be used to ignore 
	 */
	class CEmptyBitmapCallback : public CBitmapCallback {
	public:
		/**
		 *	@copydoc CBitmapCallback::operator()()
		 */
		virtual bool operator ()(size_t UNUSED(n_page),
			size_t UNUSED(n_page_num), const TBmp &UNUSED(r_t_bitmap))
		{
			return true;
		}
	};

	/**
	 *	@brief bitmap producer class
	 *	@note I did this on purpose (doing it using templated function
	 *		parameter would result in some large template functions).
	 */
	class CBitmapProducer {
	public:
		/**
		 *	@brief gets a bitmap of the specified bitmap font page
		 *	@param[in] n_page is zero-based index of the bitmap font page to be loaded
		 *	@return Returns pointer to the loaded bitmap on success, or 0 on failure.
		 */
		virtual TBmp *operator ()(size_t n_page) = 0;
	};

	/**
	 *	@brief a simple bitmap producer, reading the bitmaps from files
	 */
	class CBitmapReader : public CBitmapProducer {
	protected:
		const char *m_p_s_format; /**< @brief format string with a single %d in it */
		std::string m_s_filename; /**< @brief storage for the actual filenames */

	public:
		/**
		 *	@brief default constructor
		 *	@param[in] p_s_format is filename with a single "%d" in it
		 */
		CBitmapReader(const char *p_s_format)
			:m_p_s_format(p_s_format)
		{}

		/**
		 *	@copydoc CBitmapProducer::operator()()
		 */
		virtual TBmp *operator ()(size_t n_page)
		{
			if(!stl_ut::Format(m_s_filename, m_p_s_format, n_page))
				return 0;
			return CTgaCodec::p_Load_TGA(m_s_filename.c_str());
		}
	};

	/**
	 *	@brief CBitmapFontPage lookalike
	 */
	class CPage {
	public:
		typedef uint32_t TSizeType; /**< @brief type for storing dimensions in binary metadata */
		typedef bitmapfont2::TGlyphInfo TItemType; /**< @brief type for storing glyph information in binary metadata */
		typedef bitmapfont2::TGlyphInfo *TItemRefType; /**< @brief pointer to the type for storing glyph information in binary metadata */
		//typedef bitmapfont2::CBoxAdapter TMan; // unused

	protected:
		std::vector<TItemRefType> m_glyph_list; /**< @brief list of glyphs only on this page */
		TSizeType m_n_width; /**< @brief page width, in pixles */
		TSizeType m_n_height; /**< @brief page height, in pixles */

	public:
		/**
		 *	@param[in] n_width is page width
		 *	@param[in] n_height is page height
		 */
		inline CPage(TSizeType n_width, TSizeType n_height)
			:m_n_width(n_width), m_n_height(n_height)
		{}

		/**
		 *	@brief gets page items
		 *	@return Returns list of page items.
		 */
		const std::vector<TItemRefType> &r_ItemList() const
		{
			return m_glyph_list;
		}

		/**
		 *	@brief gets page items
		 *	@return Returns list of page items.
		 */
		std::vector<TItemRefType> &r_ItemList()
		{
			return m_glyph_list;
		}

		/**
		 *	@brief gets page width
		 *	@return Returns page width in pixels.
		 */
		inline TSizeType n_Width() const
		{
			return m_n_width;
		}

		/**
		 *	@brief gets page height
		 *	@return Returns page height in pixels.
		 */
		inline TSizeType n_Height() const
		{
			return m_n_height;
		}

		/**
		 *	@brief sets a new page size
		 *
		 *	@param[in] n_width is a new page width
		 *	@param[in] n_height is a new page height
		 *
		 *	@note This doesn't check page size against the page contents; use with caution.
		 */
		void Set_Size(TSizeType n_width, TSizeType n_height)
		{
			m_n_width = n_width;
			m_n_height = n_height;
		}
	};

	/**
	 *	@brief a list of bitmap font pages
	 */
	typedef std::list<CPage> CPageList;

	/**
	 *	@brief font texture postprocessing interface
	 */
	class CTexturePostprocessIface {
	public:
		/**
		 *	@brief postprocess one font texture image
		 *
		 *	This is used to create various font effects, such as shadows, edges, etc. The function
		 *	can appyl image processing to the entire image. The metadata block is not in the image
		 *	at the moment, its size can be used as a hint to save time in processing. Convolution
		 *	effects should not be wider than n_padding as any wider would not be rendered correctly.
		 *
		 *	@param[in,out] r_t_image is image to be postprocessed (contains grayscale glyphs)
		 *	@param[in] n_meta_block_width is width of the metadata block (in pixels)
		 *	@param[in] n_meta_block_height is height of the metadata block (in pixels)
		 *	@param[in] n_padding is useful padding of the font (in pixels)
		 */
		virtual void Postprocess(TBmp &r_t_image, size_t n_meta_block_width,
			size_t n_meta_block_height, int n_padding) = 0;
	};

	/**
	 *	@brief font texture postprocessing wrapper
	 *	@tparam CFunctor is font texture postprocessing function object
	 */
	template <class CFunctor>
	class CTexturePostprocess : public CTexturePostprocessIface {
	protected:
		CFunctor m_f; /**< @brief font texture postprocessing function object */

	public:
		/**
		 *	@brief default constructor
		 *	@param[in] f is font texture postprocessing function object
		 */
		inline CTexturePostprocess(CFunctor f)
			:m_f(f)
		{}

		/**
		 *	@copydoc CTexturePostprocessIface::Postprocess
		 */
		inline virtual void Postprocess(TBmp &r_t_image, size_t n_meta_block_width,
			size_t n_meta_block_height, int n_padding)
		{
			m_f(r_t_image, n_meta_block_width, n_meta_block_height, n_padding);
			// just call the functor
		}
	};

protected:
	bitmapfont2::TFontInfo m_t_font_info; /**< @brief font configuration */
	std::string m_s_font_face; /**< @brief font face */

	int m_n_unicode_version_id; /**< @brief required unicode version */
	std::vector<const char*> m_unicode_block_list; /**< @brief list of required unicode blocks */

	bool b_alloc_meta_blocks; /**< @brief include metadata blocks in the output (for storing generated images on the disk) */
	bool b_verify; /**< @brief verify metadata integrity (debug) */
	bool b_power_of_two_output; /**< @brief force power-of-two output */

	std::vector<bitmapfont2::TGlyphInfo> m_glyph_list; /**< @brief list of glyph info (output) */
	std::list<CPage> m_page_list; /**< @brief list of bitmap font pages (output) */
	std::vector<TBmp*> m_bitmap_list; /**< @brief list of bitmaps (optional output) */

public:
	/**
	 *	@brief default constructor; sets default bitmap font parameters
	 */
	CBitmapFont();

	/**
	 *	@brief destructor
	 */
	~CBitmapFont();

	/**
	 *	@brief gets glyph info list
	 *	@return Returns const reference to the glyph info list.
	 */
	const std::vector<bitmapfont2::TGlyphInfo> &r_Glyph_List() const;

	/**
	 *	@brief gets font page list
	 *	@return Returns const reference to font page list.
	 */
	const std::list<CPage> &r_Page_List() const;

	/**
	 *	@brief gets font texture page list
	 *	@return Returns const reference to font texture page list.
	 *	@note This list is normally empty, unless b_store_bitmaps
	 *		is set in Create() or in Load().
	 */
	const std::vector<TBmp*> &r_PageBitmap_List() const;

	/**
	 *	@brief gets name of font face
	 *	@return Returns null-terminated string, containing font face name (e.g. "arial")
	 *	@note This only returns valid values after successful call to Create() or Load().
	 */
	const char *p_s_Font_Face() const
	{
		return m_s_font_face.c_str();
	}

	/**
	 *	@brief gets font information
	 *
	 *	@return Returns font information structure.
	 *
	 *	@note This only returns valid values after successful call to Create() or Load().
	 *	@note TFontInfo is guaranteed to be valid and final when bitmap_callback
	 *		is invoked the first time.
	 */
	const bitmapfont2::TFontInfo &t_Font_Info() const
	{
		return m_t_font_info;
	}

	/**
	 *	@brief loads bitmap font from an image file
	 *
	 *	@param[in] p_s_filename is font file name (must point to a .tga image, with
	 *		optional printf integer tag in case the font has multiple pages)
	 *	@param[in] bitmap_callback is bitmap callback (the bitmaps are passed
	 *		to it as they are loaded)
	 *	@param[in] b_store_bitmaps is store bitmap flag (if set, the font texture
	 *		is stored in this, and is later accessible using r_PageBitmap_List())
	 *	@param[in] n_blank_color is color with which to clear the metadata area
	 *
	 *	@return Returns true on success, false on failure.
	 *
	 *	@note TFontInfo is guaranteed to be valid and final
	 *		when bitmap_callback is invoked the first time.
	 */
	bool Load(const char *p_s_filename,
		CBitmapCallback &bitmap_callback, bool b_store_bitmaps, uint32_t n_blank_color = 0);

	/**
	 *	@brief loads bitmap font from memory
	 *
	 *	@param[in] bitmap_producer is callback for reading bitmaps
	 *	@param[in] bitmap_callback is bitmap callback (the bitmaps are passed
	 *		to it as they are loaded)
	 *	@param[in] b_store_bitmaps is store bitmap flag (if set, the font texture
	 *		is stored in this, and is later accessible using r_PageBitmap_List())
	 *	@param[in] n_blank_color is color with which to clear the metadata area
	 *
	 *	@return Returns true on success, false on failure.
	 *
	 *	@note TFontInfo is guaranteed to be valid and final
	 *		when bitmap_callback is invoked the first time.
	 */
	bool Load(CBitmapProducer &bitmap_producer,
		CBitmapCallback &bitmap_callback, bool b_store_bitmaps, uint32_t n_blank_color = 0);

	/**
	 *	@brief reads font information from an image file
	 *
	 *	@param[in] p_s_filename is font file name (must point to a .tga image, with
	 *		optional printf integer tag in case the font has multiple pages)
	 *	@param[out] r_t_font_info is filled with font information upon successful return
	 *	@param[out] r_s_font_face is filled with font face name upon successful return
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool Read_FontInfo(const char *p_s_filename,
		bitmapfont2::TFontInfo &r_t_font_info, std::string &r_s_font_face);

	/**
	 *	@brief reads font information from memory
	 *
	 *	@param[in] bitmap_producer is callback for reading bitmaps
	 *	@param[out] r_t_font_info is filled with font information upon successful return
	 *	@param[out] r_s_font_face is filled with font face name upon successful return
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool Read_FontInfo(CBitmapProducer &bitmap_producer,
		bitmapfont2::TFontInfo &r_t_font_info, std::string &r_s_font_face);

	/**
	 *	@brief enables metadata allocation for storing the font in a file
	 *	@param[in] _b_alloc_meta_blocks is metadata allocation flag
	 *		(if set, the metadata blocks are allocated)
	 *	@note This is enabled by default.
	 */
	void Enable_MetaBlock_Allocation(bool _b_alloc_meta_blocks = true);

	/**
	 *	@brief enables metadata serialization verification
	 *	@param[in] _b_verify is metadata verification flag
	 *		(if set, the metadata blocks are read back and verified)
	 *	@note This is enabled by default.
	 */
	void Enable_Metadata_Verify(bool _b_verify = true);

	/**
	 *	@brief enables non-power-of-two output (potentially saves a little bit of space)
	 *
	 *	@param[in] b_non_power_of_two_output is non-power-of-two output flag
	 *		(if set, the output images ony contain the bounding box of the characters,
	 *		otherwise the output images are of size of power of two)
	 *
	 *	@note This is enabled by default.
	 *	@note Even if NPOT output is enabled, the OpenGL font
	 *		can still use it with power-of-two textures.
	 */
	void Enable_NPOT_Output(bool b_non_power_of_two_output = true);

	/**
	 *	@brief requests an unicode character block to be present in the font
	 *
	 *	@param[in] p_s_block_name is unicode block name as a null-terminated string
	 *		(it is not copied, it is only referenced and should not be deleted)
	 *
	 *	@return Returns true on success, false on failure.
	 *
	 *	@note By default, the "Basic Latin" block is present, if a specific block
	 *		is requested, "Basic Latin" needs to be requested specifically, otherwise
	 *		it will not be present.
	 *	@note See also CUnicodeBlocks::Codepoints_From_UnicodeNames().
	 */
	bool Request_UnicodeBlock(const char *p_s_block_name);

	/**
	 *	@brief sets unicode version for the font (affects definitions of the character blocks)
	 *	@param[in] p_s_unicode_version is unicode version name as a null-terminated string
	 *	@return Returns true on success, false on failure.
	 *	@note See also CUnicodeBlocks::n_Translate_UnicodeVersion().
	 */
	bool Set_UnicodeVersion(const char *p_s_unicode_version = "5.0.0");

	/**
	 *	@brief sets desired font decoration
	 *
	 *	@param[in] b_italic is italic flag (if set, the font is rendered as italic)
	 *	@param[in] b_underline is underline flag (if set, the font is rendered underlined)
	 *
	 *	@note Both of the above flags are disabled by default.
	 */
	void Set_FontDecoration(bool b_italic = false, bool b_underline = false);

	/**
	 *	@brief sets desired font weight
	 *	@param[in] n_font_weight is font weight (the value might be platform dependent)
	 *	@note This is 400 by default ("regular" on windows platforms).
	 */
	void Set_FontWeight(int n_font_weight = 400);

	/**
	 *	@brief sets maximum font page size
	 *	@param[in] n_max_page_size is maximum page size, in pixels
	 *	@note This is set to 2048 pixels by default (should work on Tegra 3 devices).
	 */
	void Set_Max_PageSize(size_t n_max_page_size = 2048);

	/**
	 *	@brief sets page padding
	 *	@param[in] n_page_padding is page padding, in pixels
	 *	@note This is set to 1 pixel by default (prevents stretching border pixels
	 *		in OpenGL font if GL_CLAMP_TO_EDGE is used).
	 */
	void Set_PagePadding(size_t n_page_padding = 1);

	/**
	 *	@brief sets glyph texture padding (prevents glyphs blending
	 *		into each other with mip-mapping)
	 *	@param[in] n_glyph_padding is glyph texture padding, in pixels
	 *	@note This is set to 2 pixels by default.
	 */
	void Set_GlyphTexturePadding(size_t n_glyph_padding = 2);

	/**
	 *	@brief sets glyph geometry padding (adds a bend of free space to rendered quads)
	 *	@param[in] n_glyph_padding is glyph geometry padding, in pixels
	 *	@note This is set to 2 pixels by default.
	 */
	void Set_GlyphGeometryPadding(size_t n_glyph_padding = 2);

	/**
	 *	@brief sets defaul font parameters
	 */
	void Defaults();

#if defined(_WIN32) || defined(_WIN64)

	/**
	 *	@brief loads a font from a file (windows only)
	 *
	 *	@param[in] p_s_filename is file name
	 *	@param[out] r_s_font_faces is filled with list of loaded font face names
	 *
	 *	@return Returns number of fonts loaded on success, or -1 on failure.
	 *
	 *	@note The font is loaded for the process, and should be later
	 *		deleted using Unload_FontFile().
	 *	@note In case (a portion of) the font was already in the system, the font
	 *		face list will not contain the faces that were loaded but already present.
	 *	@note This function is only present in windows.
	 *	@note If __FONT_TEXTURE_WINDOWS_AUTOLOAD_FONTS_FROM_FILE is defined,
	 *		Create() is attempting to load font files automatically, but it
	 *		will not work in case it is unable to unambiguously identify the
	 *		name of the font family that was loaded.
	 */
	static int n_Load_FontFile(const char *p_s_filename, std::vector<std::string> &r_s_font_faces);

	/**
	 *	@brief unloads a font, previously loaded using n_Load_FontFile() (windows only)
	 *	@param[in] p_s_filename is file name
	 *	@note This function is only present in windows.
	 */
	static void Unload_FontFile(const char *p_s_filename);

#endif // _WIN32 || _WIN64

	/**
	 *	@brief creates a bitmap font with the selected settings
	 *
	 *	@param[in] p_s_font_face is name of font face
	 *	@param[in] n_font_size is font size in pixels
	 *	@param[in] bitmap_callback is bitmap callback (to store the font texture)
	 *	@param[in] b_store_bitmaps is store bitmap flag (if set, the font texture
	 *		is stored in this, and is later accessible using r_PageBitmap_List())
	 *	@param[in] b_verbose is verbose flag (if set, verbose output is written to stdout)
	 *
	 *	@return Returns true on success, false on failure.
	 *
	 *	@note TFontInfo is guaranteed to be valid and final
	 *		when bitmap_callback is invoked the first time.
	 */
	inline bool Create(const char *p_s_font_face, int n_font_size,
		CBitmapCallback &bitmap_callback, bool b_store_bitmaps, bool b_verbose = false)
	{
		return _Create(p_s_font_face, n_font_size, bitmap_callback, b_store_bitmaps, 0, b_verbose);
	}

	/**
	 *	@brief creates a bitmap font with the selected settings and postprocessing
	 *
	 *	@tparam CPostprocessFunctor is postprocessing filter to apply to the bitmaps
	 *
	 *	@param[in] p_s_font_face is name of font face
	 *	@param[in] n_font_size is font size in pixels
	 *	@param[in] bitmap_callback is bitmap callback (to store the font texture)
	 *	@param[in] b_store_bitmaps is store bitmap flag (if set, the font texture
	 *		is stored in this, and is later accessible using r_PageBitmap_List())
	 *	@param[in] postprocess is postprocessing filter to apply to the bitmaps
	 *	@param[in] b_verbose is verbose flag (if set, verbose output is written to stdout)
	 *
	 *	@return Returns true on success, false on failure.
	 *
	 *	@note TFontInfo is guaranteed to be valid and final
	 *		when bitmap_callback is invoked the first time.
	 */
	template <class CPostprocessFunctor>
	inline bool Create(const char *p_s_font_face, int n_font_size,
		CBitmapCallback &bitmap_callback, bool b_store_bitmaps,
		CPostprocessFunctor postprocess, bool b_verbose = false)
	{
		CTexturePostprocess<CPostprocessFunctor> wrap(postprocess);
		return _Create(p_s_font_face, n_font_size, bitmap_callback,
			b_store_bitmaps, &wrap, b_verbose);
	}

protected:
	bool _Create(const char *p_s_font_face, int n_font_size, CBitmapCallback &bitmap_callback,
		bool b_store_bitmaps, CTexturePostprocessIface *p_postprocess, bool b_verbose);
	static inline void DeleteBitmap(TBmp *p_bitmap);
	static bool Get_GlyphImage(TBmp &r_t_bitmap, bitmapfont2::CGlyphRenderer &r_gr,
		int n_angle, TRectangle t_raster_info);
	static bool Get_GlyphInfoList(std::vector<bitmapfont2::TGlyphInfo> &glyph_info_list,
		size_t &n_discarded_num, const std::vector<std::pair<int, int> > &range_list,
		bitmapfont2::CGlyphRenderer &gr, int n_undisplayable_char = -1);
	static inline bitmapfont2::TGlyphInfo t_Deref_BoxAdapter(const bitmapfont2::TGlyphInfo *ptr);
	static bool Build_GlyphLayout(std::list<bitmapfont2::CBitmapFontPage> &page_list,
		bitmapfont2::CMetadataWriter &meta_layout, bool b_alloc_meta_blocks,
		std::vector<bitmapfont2::TGlyphInfo> &glyph_info_list,
		size_t n_max_page_size, size_t n_box_padding, size_t n_page_padding, bool b_POT_output, bool b_verbose,
		float f_rotation_thresh = .5f, float f_slack_space_resize_thresh = .1f);
	bool Load_Internal(CBitmapProducer &bitmap_producer, CBitmapCallback &bitmap_callback,
		bool b_store_bitmaps, bool b_read_font_info_only, uint32_t n_blank_color);
	CBitmapFont(const CBitmapFont &UNUSED(r_font)) {}
	CBitmapFont operator =(const CBitmapFont &UNUSED(r_font)) { return *this; }
};

#endif // !__FONT_TEXTURE_INCLUDED
