Browse Source

Changes in FontDatabase

Patryk Konopka 10 years ago
parent
commit
78571d6dd5

+ 13 - 1
Build/cmake/FileList.cmake

@@ -39,7 +39,10 @@ set(Core_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFace.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceHandle.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.h
-    ${PROJECT_SOURCE_DIR}/Source/Core/FontFamily.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceLayer.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.h
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryDatabase.h
     ${PROJECT_SOURCE_DIR}/Source/Core/LayoutBlockBox.h
     ${PROJECT_SOURCE_DIR}/Source/Core/LayoutBlockBoxSpace.h
@@ -128,7 +131,10 @@ set(Core_PUB_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontDatabase.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffect.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffectInstancer.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontFamily.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontGlyph.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontProvider.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FreeType/FontProvider.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/Geometry.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/GeometryUtilities.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/Header.h
@@ -233,6 +239,12 @@ set(Core_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceHandle.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFamily.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FontProvider.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceLayer.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontProvider.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/Geometry.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryDatabase.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryUtilities.cpp

+ 16 - 11
Include/Rocket/Core/FontDatabase.h

@@ -31,6 +31,7 @@
 #include "StringUtilities.h"
 #include "Header.h"
 #include "Font.h"
+#include "FontProvider.h"
 
 namespace Rocket {
 namespace Core {
@@ -49,6 +50,13 @@ class PropertyDictionary;
 class ROCKETCORE_API FontDatabase
 {
 public:
+
+    enum FontProviderType
+    {
+        FreeType = 0,
+        Bitmap
+    };
+
 	static bool Initialise();
 	static void Shutdown();
 
@@ -67,7 +75,7 @@ public:
 	/// @param[in] data The font data.
 	/// @param[in] data_length Length of the data.
 	/// @return True if the face was loaded successfully, false otherwise.
-	static bool LoadFontFace(const byte* data, int data_length);
+    static bool LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length);
 	/// Adds a new font face to the database, loading from memory.
 	/// @param[in] data The font data.
 	/// @param[in] data_length Length of the data.
@@ -75,7 +83,7 @@ public:
 	/// @param[in] style The style of the face (normal or italic).
 	/// @param[in] weight The weight of the face (normal or bold).
 	/// @return True if the face was loaded successfully, false otherwise.
-	static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight);
+    static bool LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight);
 
 	/// Returns a handle to a font face that can be used to position and render text. This will return the closest match
 	/// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a
@@ -99,20 +107,17 @@ public:
 	/// @param[in] The effect to release.
 	static void ReleaseFontEffect(const FontEffect* effect);
 
+    static void AddFontProvider(FontProvider * provider);
+
+    static void RemoveFontProvider(FontProvider * provider);
+
 private:
 	FontDatabase(void);
 	~FontDatabase(void);
 
-	// Adds a loaded face to the appropriate font family.
-	bool AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream);
-	// Loads a FreeType face.
-	void* LoadFace(const String& file_name);
-	// Loads a FreeType face from memory.
-	void* LoadFace(const byte* data, int data_length, const String& source, bool local_data);
-
-	typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap;
-	FontFamilyMap font_families;
+    typedef std::vector< FontProvider *> FontProviderTable;
 
+    static FontProviderTable font_provider_table;
 	static FontDatabase* instance;
 };
 

+ 2 - 2
Source/Core/FontFamily.h → Include/Rocket/Core/FontFamily.h

@@ -28,7 +28,7 @@
 #ifndef ROCKETCOREFONTFAMILY_H
 #define ROCKETCOREFONTFAMILY_H
 
-#include "../../Include/Rocket/Core/Font.h"
+#include "Font.h"
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
@@ -54,7 +54,7 @@ public:
 	/// @param[in] weight The weight of the new face.
 	/// @param[in] release_stream True if the application must free the face's memory stream.
 	/// @return True if the face was loaded successfully, false otherwise.
-	bool AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream);
+    bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream);
 
 	/// Returns a handle to the most appropriate font in the family, at the correct size.
 	/// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges.

+ 72 - 0
Include/Rocket/Core/FontProvider.h

@@ -0,0 +1,72 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFONTPROVIDER_H
+#define ROCKETCOREFONTPROVIDER_H
+
+#include <Rocket/Core/StringUtilities.h>
+#include <Rocket/Core/Font.h>
+#include <Rocket/Core/Header.h>
+
+namespace Rocket {
+namespace Core {
+
+class FontFaceHandle;
+class FontFamily;
+
+/**
+    The font database contains all font families currently in use by Rocket.
+    @author Peter Curry
+ */
+
+class ROCKETCORE_API FontProvider
+{
+public:
+
+    /// Returns a handle to a font face that can be used to position and render text. This will return the closest match
+    /// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a
+    /// valid handle.
+    /// @param[in] family The family of the desired font handle.
+    /// @param[in] charset The set of characters required in the font face, as a comma-separated list of unicode ranges.
+    /// @param[in] style The style of the desired font handle.
+    /// @param[in] weight The weight of the desired font handle.
+    /// @param[in] size The size of desired handle, in points.
+    /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise.
+    virtual FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) = 0;
+
+protected:
+
+    FontFamily* GetFontFamily(const String& family);
+
+    typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap;
+    FontFamilyMap font_families;
+};
+
+}
+}
+
+#endif

+ 112 - 0
Include/Rocket/Core/FreeType/FontProvider.h

@@ -0,0 +1,112 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFREETYPEFONTPROVIDER_H
+#define ROCKETCOREFREETYPEFONTPROVIDER_H
+
+#include <Rocket/Core/StringUtilities.h>
+#include <Rocket/Core/Font.h>
+#include <Rocket/Core/FontProvider.h>
+
+namespace Rocket {
+namespace Core {
+
+
+class FontEffect;
+class FontFaceHandle;
+class PropertyDictionary;
+
+namespace FreeType {
+
+class FontFamily;
+
+/**
+    The font database contains all font families currently in use by Rocket.
+    @author Peter Curry
+ */
+
+class ROCKETCORE_API FontProvider : public Rocket::Core::FontProvider
+{
+public:
+    static bool Initialise();
+    static void Shutdown();
+
+    /// Adds a new font face to the database. The face's family, style and weight will be determined from the face itself.
+    /// @param[in] file_name The file to load the face from.
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const String& file_name);
+    /// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
+    /// @param[in] file_name The file to load the face from.
+    /// @param[in] family The family to add the face to.
+    /// @param[in] style The style of the face (normal or italic).
+    /// @param[in] weight The weight of the face (normal or bold).
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight);
+    /// Adds a new font face to the database, loading from memory. The face's family, style and weight will be determined from the face itself.
+    /// @param[in] data The font data.
+    /// @param[in] data_length Length of the data.
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const byte* data, int data_length);
+    /// Adds a new font face to the database, loading from memory.
+    /// @param[in] data The font data.
+    /// @param[in] data_length Length of the data.
+    /// @param[in] family The family to add the face to.
+    /// @param[in] style The style of the face (normal or italic).
+    /// @param[in] weight The weight of the face (normal or bold).
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight);
+
+    /// Returns a handle to a font face that can be used to position and render text. This will return the closest match
+    /// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a
+    /// valid handle.
+    /// @param[in] family The family of the desired font handle.
+    /// @param[in] charset The set of characters required in the font face, as a comma-separated list of unicode ranges.
+    /// @param[in] style The style of the desired font handle.
+    /// @param[in] weight The weight of the desired font handle.
+    /// @param[in] size The size of desired handle, in points.
+    /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise.
+    virtual FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size);
+
+private:
+    FontProvider(void);
+    ~FontProvider(void);
+
+    // Adds a loaded face to the appropriate font family.
+    bool AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream);
+    // Loads a FreeType face.
+    void* LoadFace(const String& file_name);
+    // Loads a FreeType face from memory.
+    void* LoadFace(const byte* data, int data_length, const String& source, bool local_data);
+
+    static FontProvider* instance;
+};
+
+}
+}
+}
+
+#endif

+ 38 - 160
Source/Core/FontDatabase.cpp

@@ -26,9 +26,10 @@
  */
 
 #include "precompiled.h"
-#include "../../Include/Rocket/Core/FontDatabase.h"
-#include "FontFamily.h"
-#include "../../Include/Rocket/Core.h"
+#include <Rocket/Core/FontDatabase.h>
+#include <Rocket/Core/FontFamily.h>
+#include <Rocket/Core.h>
+#include <Rocket/Core/FreeType/FontProvider.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
@@ -60,13 +61,8 @@ bool FontDatabase::Initialise()
 	{
 		new FontDatabase();
 
-		FT_Error result = FT_Init_FreeType(&ft_library);
-		if (result != 0)
-		{
-			Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result);
-			Shutdown();
-			return false;
-		}
+        if(!FreeType::FontProvider::Initialise())
+            return false;
 	}
 
 	return true;
@@ -76,14 +72,7 @@ void FontDatabase::Shutdown()
 {
 	if (instance != NULL)
 	{
-		for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i)
-			delete (*i).second;
-
-		if (ft_library != NULL)
-		{
-			FT_Done_FreeType(ft_library);
-			ft_library = NULL;
-		}
+        FreeType::FontProvider::Shutdown();
 
 		delete instance;
 	}
@@ -92,105 +81,45 @@ void FontDatabase::Shutdown()
 // Loads a new font face.
 bool FontDatabase::LoadFontFace(const String& file_name)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
-		return false;
-	}
-
-	Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
-	Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
-
-	if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return false;
-	}
+    return FreeType::FontProvider::LoadFontFace(file_name);
 }
 
 // Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
 bool FontDatabase::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
-		return false;
-	}
-
-	if (instance->AddFace(ft_face, family, style, weight, true))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return false;
-	}
+    return FreeType::FontProvider::LoadFontFace(file_name, family, style, weight);
 }
 
 // Adds a new font face to the database, loading from memory.
-bool FontDatabase::LoadFontFace(const byte* data, int data_length)
+bool FontDatabase::LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
-		return false;
-	}
-
-	Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
-	Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
-
-	if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return false;
-	}
+    return FreeType::FontProvider::LoadFontFace(data, data_length);
 }
 
 // Adds a new font face to the database, loading from memory, ignoring any family, style and weight information stored in the face itself.
-bool FontDatabase::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
+bool FontDatabase::LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
-		return false;
-	}
-
-	if (instance->AddFace(ft_face, family, style, weight, false))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return false;
-	}
+    return FreeType::FontProvider::LoadFontFace(data, data_length, family, style, weight);
 }
 
 // Returns a handle to a font face that can be used to position and render text.
 FontFaceHandle* FontDatabase::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size)
 {
-	FontFamilyMap::iterator iterator = instance->font_families.find(family);
-	if (iterator == instance->font_families.end())
-		return NULL;
+    size_t provider_index, provider_count;
 
-	return (*iterator).second->GetFaceHandle(charset, style, weight, size);
+    provider_count = font_provider_table.size();
+
+    for(provider_index = 0; provider_index < provider_count; ++provider_index)
+    {
+        FontFaceHandle * face_handle = font_provider_table[ provider_index ]->GetFontFaceHandle(family, charset, style, weight, size);
+
+        if(face_handle)
+        {
+            return face_handle;
+        }
+    }
+
+    return NULL;
 }
 
 // Returns a font effect, either a newly-instanced effect from the factory or an identical shared
@@ -255,72 +184,21 @@ void FontDatabase::ReleaseFontEffect(const FontEffect* effect)
 	}
 }
 
-// Adds a loaded face to the appropriate font family.
-bool FontDatabase::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream)
+void FontDatabase::AddFontProvider(FontProvider * provider)
 {
-	FontFamily* font_family = NULL;
-	FontFamilyMap::iterator iterator = instance->font_families.find(family);
-	if (iterator != instance->font_families.end())
-		font_family = (*iterator).second;
-	else
-	{
-		font_family = new FontFamily(family);
-		instance->font_families[family] = font_family;
-	}
-
-	return font_family->AddFace((FT_Face) face, style, weight, release_stream);
+    instance->font_provider_table.push_back(provider);
 }
 
-// Loads a FreeType face.
-void* FontDatabase::LoadFace(const String& file_name)
+void FontDatabase::RemoveFontProvider(FontProvider * provider)
 {
-	FileInterface* file_interface = GetFileInterface();
-	FileHandle handle = file_interface->Open(file_name);
-
-	if (!handle)
-	{
-		return NULL;
-	}
-
-	size_t length = file_interface->Length(handle);
-
-	FT_Byte* buffer = new FT_Byte[length];
-	file_interface->Read(buffer, length, handle);
-	file_interface->Close(handle);
-
-	return LoadFace(buffer, (int)length, file_name, true);
-}
-
-// Loads a FreeType face from memory.
-void* FontDatabase::LoadFace(const byte* data, int data_length, const String& source, bool local_data)
-{
-	FT_Face face = NULL;
-	int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face);
-	if (error != 0)
-	{
-		Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString());
-		if (local_data)
-			delete[] data;
-
-		return NULL;
-	}
-
-	// Initialise the character mapping on the face.
-	if (face->charmap == NULL)
-	{
-		FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN);
-		if (face->charmap == NULL)
-		{
-			Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString());
-			FT_Done_Face(face);
-			if (local_data)
-				delete[] data;
-
-			return NULL;
-		}
-	}
-
-	return face;
+    for(FontProviderTable::iterator i = instance->font_provider_table.begin(); i != instance->font_provider_table.end(); ++i)
+    {
+        if(*i == provider)
+        {
+            instance->font_provider_table.erase(i);
+            return;
+        }
+    }
 }
 
 }

+ 3 - 3
Source/Core/FontFamily.cpp

@@ -26,7 +26,7 @@
  */
 
 #include "precompiled.h"
-#include "FontFamily.h"
+#include "../../Include/Rocket/Core/FontFamily.h"
 #include "FontFace.h"
 
 namespace Rocket {
@@ -43,9 +43,9 @@ FontFamily::~FontFamily()
 }
 
 // Adds a new face to the family.
-bool FontFamily::AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream)
+bool FontFamily::AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream)
 {
-	FontFace* face = new FontFace(ft_face, style, weight, release_stream);
+    FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream);
 	font_faces.push_back(face);
 
 	return true;

+ 50 - 0
Source/Core/FontProvider.cpp

@@ -0,0 +1,50 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <Rocket/Core/FontProvider.h>
+#include <Rocket/Core/FontFamily.h>
+
+namespace Rocket {
+namespace Core {
+
+FontFamily* FontProvider::GetFontFamily(const String& family)
+{
+    FontFamily* font_family = NULL;
+    FontFamilyMap::iterator iterator = font_families.find(family);
+    if (iterator != font_families.end())
+        font_family = (*iterator).second;
+    else
+    {
+        font_family = new FontFamily(family);
+        font_families[family] = font_family;
+    }
+
+    return font_family;
+}
+
+}
+}

+ 160 - 0
Source/Core/FreeType/FontFace.cpp

@@ -0,0 +1,160 @@
+///*
+// * This source file is part of libRocket, the HTML/CSS Interface Middleware
+// *
+// * For the latest information, see http://www.librocket.com
+// *
+// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a copy
+// * of this software and associated documentation files (the "Software"), to deal
+// * in the Software without restriction, including without limitation the rights
+// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// * copies of the Software, and to permit persons to whom the Software is
+// * furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included in
+// * all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// * THE SOFTWARE.
+// *
+// */
+
+//#include "../precompiled.h"
+//#include "FontFace.h"
+//#include "FontFaceHandle.h"
+//#include "../../Include/Rocket/Core/Log.h"
+
+//namespace Rocket {
+//namespace Core {
+
+//FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream)
+//{
+//	face = _face;
+//	style = _style;
+//	weight = _weight;
+
+//	release_stream = _release_stream;
+//}
+
+//FontFace::~FontFace()
+//{
+//	for (HandleMap::iterator iterator = handles.begin(); iterator != handles.end(); ++iterator)
+//	{
+//		HandleList& handle_list = (*iterator).second;
+//		for (size_t i = 0; i < handle_list.size(); ++i)
+//			handle_list[i]->RemoveReference();
+//	}
+
+//	ReleaseFace();
+//}
+
+//// Returns the style of the font face.
+//Font::Style FontFace::GetStyle() const
+//{
+//	return style;
+//}
+
+//// Returns the weight of the font face.
+//Font::Weight FontFace::GetWeight() const
+//{
+//	return weight;
+//}
+
+//// Returns a handle for positioning and rendering this face at the given size.
+//FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
+//{
+//	UnicodeRangeList charset;
+
+//	HandleMap::iterator iterator = handles.find(size);
+//	if (iterator != handles.end())
+//	{
+//		const HandleList& handles = (*iterator).second;
+
+//		// Check all the handles if their charsets match the requested one exactly (ie, were specified by the same
+//		// string).
+//		String raw_charset(_raw_charset);
+//		for (size_t i = 0; i < handles.size(); ++i)
+//		{
+//			if (handles[i]->GetRawCharset() == _raw_charset)
+//			{
+//				handles[i]->AddReference();
+//				return handles[i];
+//			}
+//		}
+
+//		// Check all the handles if their charsets contain the requested charset.
+//		if (!UnicodeRange::BuildList(charset, raw_charset))
+//		{
+//			Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString());
+//			return NULL;
+//		}
+
+//		for (size_t i = 0; i < handles.size(); ++i)
+//		{
+//			bool range_contained = true;
+
+//			const UnicodeRangeList& handle_charset = handles[i]->GetCharset();
+//			for (size_t j = 0; j < charset.size() && range_contained; ++j)
+//			{
+//				if (!charset[j].IsContained(handle_charset))
+//					range_contained = false;
+//			}
+
+//			if (range_contained)
+//			{
+//				handles[i]->AddReference();
+//				return handles[i];
+//			}
+//		}
+//	}
+
+//	// See if this face has been released.
+//	if (face == NULL)
+//	{
+//		Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle.");
+//		return NULL;
+//	}
+
+//	// Construct and initialise the new handle.
+//	FontFaceHandle* handle = new FontFaceHandle();
+//	if (!handle->Initialise(face, _raw_charset, size))
+//	{
+//		handle->RemoveReference();
+//		return NULL;
+//	}
+
+//	// Save the handle, and add a reference for the callee. The initial reference will be removed when the font face
+//	// releases it.
+//	if (iterator != handles.end())
+//		(*iterator).second.push_back(handle);
+//	else
+//		handles[size] = HandleList(1, handle);
+
+//	handle->AddReference();
+
+//	return handle;
+//}
+
+//// Releases the face's FreeType face structure.
+//void FontFace::ReleaseFace()
+//{
+//	if (face != NULL)
+//	{
+//		FT_Byte* face_memory = face->stream->base;
+//		FT_Done_Face(face);
+
+//		if (release_stream)
+//			delete[] face_memory;
+
+//		face = NULL;
+//	}
+//}
+
+//}
+//}

+ 82 - 0
Source/Core/FreeType/FontFace.h

@@ -0,0 +1,82 @@
+///*
+// * This source file is part of libRocket, the HTML/CSS Interface Middleware
+// *
+// * For the latest information, see http://www.librocket.com
+// *
+// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a copy
+// * of this software and associated documentation files (the "Software"), to deal
+// * in the Software without restriction, including without limitation the rights
+// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// * copies of the Software, and to permit persons to whom the Software is
+// * furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included in
+// * all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// * THE SOFTWARE.
+// *
+// */
+
+//#ifndef ROCKETCOREFONTFACE_H
+//#define ROCKETCOREFONTFACE_H
+
+//#include "../../../Include/Rocket/Core/Font.h"
+//#include <ft2build.h>
+//#include FT_FREETYPE_H
+
+//namespace Rocket {
+//namespace Core {
+
+//class FontFaceHandle;
+
+///**
+//	@author Peter Curry
+// */
+
+//class FontFace
+//{
+//public:
+//	FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream);
+//	~FontFace();
+
+//	/// Returns the style of the font face.
+//	/// @return The font face's style.
+//	Font::Style GetStyle() const;
+//	/// Returns the weight of the font face.
+//	/// @return The font face's weight.
+//	Font::Weight GetWeight() const;
+
+//	/// Returns a handle for positioning and rendering this face at the given size.
+//	/// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges.
+//	/// @param[in] size The size of the desired handle, in points.
+//	/// @return The shared font handle.
+//	FontFaceHandle* GetHandle(const String& charset, int size);
+
+//	/// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed,
+//	/// but existing ones can still be fetched.
+//	void ReleaseFace();
+
+//private:
+//	FT_Face face;
+//	Font::Style style;
+//	Font::Weight weight;
+
+//	bool release_stream;
+
+//	typedef std::vector< FontFaceHandle* > HandleList;
+//	typedef std::map< int, HandleList > HandleMap;
+//	HandleMap handles;
+//};
+
+//}
+//}
+
+//#endif

+ 566 - 0
Source/Core/FreeType/FontFaceHandle.cpp

@@ -0,0 +1,566 @@
+///*
+// * This source file is part of libRocket, the HTML/CSS Interface Middleware
+// *
+// * For the latest information, see http://www.librocket.com
+// *
+// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a copy
+// * of this software and associated documentation files (the "Software"), to deal
+// * in the Software without restriction, including without limitation the rights
+// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// * copies of the Software, and to permit persons to whom the Software is
+// * furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included in
+// * all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// * THE SOFTWARE.
+// *
+// */
+
+//#include "precompiled.h"
+//#include "FontFaceHandle.h"
+//#include <algorithm>
+//#include "../../Include/Rocket/Core.h"
+//#include "FontFaceLayer.h"
+//#include "TextureLayout.h"
+
+//namespace Rocket {
+//namespace Core {
+
+//class FontEffectSort
+//{
+//public:
+//	bool operator()(const FontEffect* lhs, const FontEffect* rhs)
+//	{
+//		return lhs->GetZIndex() < rhs->GetZIndex();
+//	}
+//};
+
+//FontFaceHandle::FontFaceHandle()
+//{
+//	size = 0;
+//	average_advance = 0;
+//	x_height = 0;
+//	line_height = 0;
+//	baseline = 0;
+
+//	underline_position = 0;
+//	underline_thickness = 0;
+
+//	ft_face = NULL;
+
+//	base_layer = NULL;
+//}
+
+//FontFaceHandle::~FontFaceHandle()
+//{
+//	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+//		delete[] i->bitmap_data;
+
+//	for (FontLayerMap::iterator i = layers.begin(); i != layers.end(); ++i)
+//		delete i->second;
+//}
+
+//// Initialises the handle so it is able to render text.
+//bool FontFaceHandle::Initialise(FT_Face ft_face, const String& _charset, int _size)
+//{
+//	size = _size;
+
+//	raw_charset = _charset;
+//	if (!UnicodeRange::BuildList(charset, raw_charset))
+//	{
+//		Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString());
+//		return false;
+//	}
+
+//	// Set the character size on the font face.
+//	FT_Error error = FT_Set_Char_Size(ft_face, 0, size << 6, 0, 0);
+//	if (error != 0)
+//	{
+//		Log::Message(Log::LT_ERROR, "Unable to set the character size '%d' on the font face '%s %s'.", size, ft_face->family_name, ft_face->style_name);
+//		return false;
+//	}
+
+//	this->ft_face = ft_face;
+
+//	// find the maximum character we are interested in
+//	max_codepoint = 0;
+//	for (size_t i = 0; i < charset.size(); ++i)
+//		max_codepoint = Math::Max(max_codepoint, charset[i].max_codepoint);
+
+//	// Construct the list of the characters specified by the charset.
+//	glyphs.resize(max_codepoint+1, FontGlyph());
+//	for (size_t i = 0; i < charset.size(); ++i)
+//		BuildGlyphMap(charset[i]);
+
+//	// Generate the metrics for the handle.
+//	GenerateMetrics();
+
+//	// Generate the default layer and layer configuration.
+//	base_layer = GenerateLayer(NULL);
+//	layer_configurations.push_back(LayerConfiguration());
+//	layer_configurations.back().push_back(base_layer);
+
+
+//	return true;
+//}
+
+//// Returns the point size of this font face.
+//int FontFaceHandle::GetSize() const
+//{
+//	return size;
+//}
+
+//// Returns the average advance of all glyphs in this font face.
+//int FontFaceHandle::GetCharacterWidth() const
+//{
+//	return average_advance;
+//}
+
+//// Returns the pixel height of a lower-case x in this font face.
+//int FontFaceHandle::GetXHeight() const
+//{
+//	return x_height;
+//}
+
+//// Returns the default height between this font face's baselines.
+//int FontFaceHandle::GetLineHeight() const
+//{
+//	return line_height;
+//}
+
+//// Returns the font's baseline.
+//int FontFaceHandle::GetBaseline() const
+//{
+//	return baseline;
+//}
+
+//// Returns the font's glyphs.
+//const FontGlyphList& FontFaceHandle::GetGlyphs() const
+//{
+//	return glyphs;
+//}
+
+//// Returns the width a string will take up if rendered with this handle.
+//int FontFaceHandle::GetStringWidth(const WString& string, word prior_character) const
+//{
+//	int width = 0;
+
+//	for (size_t i = 0; i < string.Length(); i++)
+//	{
+//		word character_code = string[i];
+
+//		if (character_code >= glyphs.size())
+//			continue;
+//		const FontGlyph &glyph = glyphs[character_code];
+
+//		// Adjust the cursor for the kerning between this character and the previous one.
+//		if (prior_character != 0)
+//			width += GetKerning(prior_character, string[i]);
+//		// Adjust the cursor for this character's advance.
+//		width += glyph.advance;
+
+//		prior_character = character_code;
+//	}
+
+//	return width;
+//}
+
+//// Generates, if required, the layer configuration for a given array of font effects.
+//int FontFaceHandle::GenerateLayerConfiguration(FontEffectMap& font_effects)
+//{
+//	if (font_effects.empty())
+//		return 0;
+
+//	// Prepare a list of effects, sorted by z-index.
+//	FontEffectList sorted_effects;
+//	for (FontEffectMap::const_iterator i = font_effects.begin(); i != font_effects.end(); ++i)
+//		sorted_effects.push_back(i->second);
+
+//	std::sort(sorted_effects.begin(), sorted_effects.end(), FontEffectSort());
+
+//	// Check each existing configuration for a match with this arrangement of effects.
+//	int configuration_index = 1;
+//	for (; configuration_index < (int) layer_configurations.size(); ++configuration_index)
+//	{
+//		const LayerConfiguration& configuration = layer_configurations[configuration_index];
+
+//		// Check the size is correct. For a math, there should be one layer in the configuration
+//		// plus an extra for the base layer.
+//		if (configuration.size() != sorted_effects.size() + 1)
+//			continue;
+
+//		// Check through each layer, checking it was created by the same effect as the one we're
+//		// checking.
+//		size_t effect_index = 0;
+//		for (size_t i = 0; i < configuration.size(); ++i)
+//		{
+//			// Skip the base layer ...
+//			if (configuration[i]->GetFontEffect() == NULL)
+//				continue;
+
+//			// If the ith layer's effect doesn't match the equivalent effect, then this
+//			// configuration can't match.
+//			if (configuration[i]->GetFontEffect() != sorted_effects[effect_index])
+//				break;
+
+//			// Check the next one ...
+//			++effect_index;
+//		}
+
+//		if (effect_index == sorted_effects.size())
+//			return configuration_index;
+//	}
+
+//	// No match, so we have to generate a new layer configuration.
+//	layer_configurations.push_back(LayerConfiguration());
+//	LayerConfiguration& layer_configuration = layer_configurations.back();
+
+//	bool added_base_layer = false;
+
+//	for (size_t i = 0; i < sorted_effects.size(); ++i)
+//	{
+//		if (!added_base_layer &&
+//			sorted_effects[i]->GetZIndex() >= 0)
+//		{
+//			layer_configuration.push_back(base_layer);
+//			added_base_layer = true;
+//		}
+
+//		layer_configuration.push_back(GenerateLayer(sorted_effects[i]));
+//	}
+
+//	// Add the base layer now if we still haven't added it.
+//	if (!added_base_layer)
+//		layer_configuration.push_back(base_layer);
+
+//	return (int) (layer_configurations.size() - 1);
+//}
+
+//// Generates the texture data for a layer (for the texture database).
+//bool FontFaceHandle::GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id)
+//{
+//	FontLayerMap::iterator layer_iterator = layers.find(layer_id);
+//	if (layer_iterator == layers.end())
+//		return false;
+
+//	return layer_iterator->second->GenerateTexture(texture_data, texture_dimensions, texture_id);
+//}
+
+//// Generates the geometry required to render a single line of text.
+//int FontFaceHandle::GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration_index) const
+//{
+//	int geometry_index = 0;
+//	int line_width = 0;
+
+//	ROCKET_ASSERT(layer_configuration_index >= 0);
+//	ROCKET_ASSERT(layer_configuration_index < (int) layer_configurations.size());
+
+//	// Fetch the requested configuration and generate the geometry for each one.
+//	const LayerConfiguration& layer_configuration = layer_configurations[layer_configuration_index];
+//	for (size_t i = 0; i < layer_configuration.size(); ++i)
+//	{
+//		FontFaceLayer* layer = layer_configuration[i];
+
+//		Colourb layer_colour;
+//		if (layer == base_layer)
+//			layer_colour = colour;
+//		else
+//			layer_colour = layer->GetColour();
+
+//		// Resize the geometry list if required.
+//		if ((int) geometry.size() < geometry_index + layer->GetNumTextures())
+//			geometry.resize(geometry_index + layer->GetNumTextures());
+
+//		// Bind the textures to the geometries.
+//		for (int i = 0; i < layer->GetNumTextures(); ++i)
+//			geometry[geometry_index + i].SetTexture(layer->GetTexture(i));
+
+//		line_width = 0;
+//		word prior_character = 0;
+
+//		const word* string_iterator = string.CString();
+//		const word* string_end = string.CString() + string.Length();
+
+//		for (; string_iterator != string_end; string_iterator++)
+//		{
+//			if (*string_iterator >= glyphs.size())
+//				continue;
+//			const FontGlyph &glyph = glyphs[*string_iterator];
+
+//			// Adjust the cursor for the kerning between this character and the previous one.
+//			if (prior_character != 0)
+//				line_width += GetKerning(prior_character, *string_iterator);
+
+//			layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour);
+
+//			line_width += glyph.advance;
+//			prior_character = *string_iterator;
+//		}
+
+//		geometry_index += layer->GetNumTextures();
+//	}
+
+//	// Cull any excess geometry from a previous generation.
+//	geometry.resize(geometry_index);
+
+//	return line_width;
+//}
+
+//// Generates the geometry required to render a line above, below or through a line of text.
+//void FontFaceHandle::GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const
+//{
+//	std::vector< Vertex >& line_vertices = geometry->GetVertices();
+//	std::vector< int >& line_indices = geometry->GetIndices();
+
+//	float offset;
+//	switch (height)
+//	{
+//		case Font::UNDERLINE:			offset = -underline_position; break;
+//		case Font::OVERLINE:			// where to place? offset = -line_height - underline_position; break;
+//		case Font::STRIKE_THROUGH:		// where to place? offset = -line_height * 0.5f; break;
+//		default:						return;
+//	}
+
+//	line_vertices.resize(line_vertices.size() + 4);
+//	line_indices.resize(line_indices.size() + 6);
+//	GeometryUtilities::GenerateQuad(&line_vertices[0] + (line_vertices.size() - 4), &line_indices[0] + (line_indices.size() - 6), Vector2f(position.x, position.y + offset), Vector2f((float) width, underline_thickness), colour, (int)line_vertices.size() - 4);
+//}
+
+//// Returns the font face's raw charset (the charset range as a string).
+//const String& FontFaceHandle::GetRawCharset() const
+//{
+//	return raw_charset;
+//}
+
+//// Returns the font face's charset.
+//const UnicodeRangeList& FontFaceHandle::GetCharset() const
+//{
+//	return charset;
+//}
+
+//// Destroys the handle.
+//void FontFaceHandle::OnReferenceDeactivate()
+//{
+//	delete this;
+//}
+
+//void FontFaceHandle::GenerateMetrics()
+//{
+//	line_height = ft_face->size->metrics.height >> 6;
+//	baseline = line_height - (ft_face->size->metrics.ascender >> 6);
+
+//	underline_position = FT_MulFix(ft_face->underline_position, ft_face->size->metrics.y_scale) / float(1 << 6);
+//	underline_thickness = FT_MulFix(ft_face->underline_thickness, ft_face->size->metrics.y_scale) / float(1 << 6);
+//	underline_thickness = Math::Max(underline_thickness, 1.0f);
+
+//	average_advance = 0;
+//	unsigned int num_visible_glyphs = 0;
+//	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+//	{
+//		if (i->advance)
+//		{
+//			average_advance += i->advance;
+//			num_visible_glyphs++;
+//		}
+//	}
+
+//	// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
+//	if (num_visible_glyphs)
+//		average_advance = Math::RealToInteger((float) average_advance / (num_visible_glyphs * 0.9f));
+
+//	// Determine the x-height of this font face.
+//	word x = (word) 'x';
+//	int index = FT_Get_Char_Index(ft_face, x);
+//	if (FT_Load_Glyph(ft_face, index, 0) == 0)
+//		x_height = ft_face->glyph->metrics.height >> 6;
+//	else
+//		x_height = 0;
+//}
+
+//void FontFaceHandle::BuildGlyphMap(const UnicodeRange& unicode_range)
+//{
+//	for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code)
+//	{
+//		int index = FT_Get_Char_Index(ft_face, character_code);
+//		if (index != 0)
+//		{
+//			FT_Error error = FT_Load_Glyph(ft_face, index, 0);
+//			if (error != 0)
+//			{
+//				Log::Message(Log::LT_WARNING, "Unable to load glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
+//				continue;
+//			}
+
+//			error = FT_Render_Glyph(ft_face->glyph, FT_RENDER_MODE_NORMAL);
+//			if (error != 0)
+//			{
+//				Log::Message(Log::LT_WARNING, "Unable to render glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
+//				continue;
+//			}
+
+//			FontGlyph glyph;
+//			glyph.character = character_code;
+//			BuildGlyph(glyph, ft_face->glyph);
+//			glyphs[character_code] = glyph;
+//		}
+//	}
+//}
+
+//void FontFaceHandle::BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph)
+//{
+//	// Set the glyph's dimensions.
+//	glyph.dimensions.x = ft_glyph->metrics.width >> 6;
+//	glyph.dimensions.y = ft_glyph->metrics.height >> 6;
+
+//	// Set the glyph's bearing.
+//	glyph.bearing.x = ft_glyph->metrics.horiBearingX >> 6;
+//	glyph.bearing.y = ft_glyph->metrics.horiBearingY >> 6;
+
+//	// Set the glyph's advance.
+//	glyph.advance = ft_glyph->metrics.horiAdvance >> 6;
+
+//	// Set the glyph's bitmap dimensions.
+//	glyph.bitmap_dimensions.x = ft_glyph->bitmap.width;
+//	glyph.bitmap_dimensions.y = ft_glyph->bitmap.rows;
+
+//	// Copy the glyph's bitmap data from the FreeType glyph handle to our glyph handle.
+//	if (glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y != 0)
+//	{
+//		// Check the pixel mode is supported.
+//		if (ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
+//			ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
+//		{
+//			glyph.bitmap_data = NULL;
+//			Log::Message(Log::LT_WARNING, "Unable to render glyph on the font face '%s %s'; unsupported pixel mode (%d).", ft_glyph->face->family_name, ft_glyph->face->style_name, ft_glyph->bitmap.pixel_mode);
+//		}
+//		else
+//		{
+//			glyph.bitmap_data = new byte[glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y];
+
+//			byte* source_bitmap = ft_glyph->bitmap.buffer;
+//			byte* destination_bitmap = glyph.bitmap_data;
+
+//			// Copy the bitmap data into the newly-allocated space on our glyph.
+//			switch (ft_glyph->bitmap.pixel_mode)
+//			{
+//				// Unpack 1-bit data into 8-bit.
+//				case FT_PIXEL_MODE_MONO:
+//				{
+//					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
+//					{
+//						int mask = 0x80;
+//						byte* source_byte = source_bitmap;
+//						for (int j = 0; j < glyph.bitmap_dimensions.x; ++j)
+//						{
+//							if ((*source_byte & mask) == mask)
+//								destination_bitmap[j] = 255;
+//							else
+//								destination_bitmap[j] = 0;
+
+//							mask >>= 1;
+//							if (mask <= 0)
+//							{
+//								mask = 0x80;
+//								++source_byte;
+//							}
+//						}
+
+//						destination_bitmap += glyph.bitmap_dimensions.x;
+//						source_bitmap += ft_glyph->bitmap.pitch;
+//					}
+//				}
+//				break;
+
+//				// Directly copy 8-bit data.
+//				case FT_PIXEL_MODE_GRAY:
+//				{
+//					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
+//					{
+//						memcpy(destination_bitmap, source_bitmap, glyph.bitmap_dimensions.x);
+//						destination_bitmap += glyph.bitmap_dimensions.x;
+//						source_bitmap += ft_glyph->bitmap.pitch;
+//					}
+//				}
+//				break;
+//			}
+//		}
+//	}
+//	else
+//		glyph.bitmap_data = NULL;
+//}
+
+//int FontFaceHandle::GetKerning(word lhs, word rhs) const
+//{
+//	if (!FT_HAS_KERNING(ft_face))
+//		return 0;
+
+//	FT_Vector ft_kerning;
+
+//	FT_Error ft_error = FT_Get_Kerning(ft_face,
+//		FT_Get_Char_Index(ft_face, lhs), FT_Get_Char_Index(ft_face, rhs),
+//		FT_KERNING_DEFAULT, &ft_kerning);
+
+//	if (ft_error != 0)
+//		return 0;
+
+//	int kerning = ft_kerning.x >> 6;
+//	return kerning;
+//}
+
+//// Generates (or shares) a layer derived from a font effect.
+//FontFaceLayer* FontFaceHandle::GenerateLayer(FontEffect* font_effect)
+//{
+//	// See if this effect has been instanced before, as part of a different configuration.
+//	FontLayerMap::iterator i = layers.find(font_effect);
+//	if (i != layers.end())
+//		return i->second;
+
+//	FontFaceLayer* layer = new FontFaceLayer();
+//	layers[font_effect] = layer;
+
+//	if (font_effect == NULL)
+//	{
+//		layer->Initialise(this);
+//	}
+//	else
+//	{
+//		// Determine which, if any, layer the new layer should copy its geometry and textures from.
+//		FontFaceLayer* clone = NULL;
+//		bool deep_clone = true;
+//		String generation_key;
+
+//		if (!font_effect->HasUniqueTexture())
+//		{
+//			clone = base_layer;
+//			deep_clone = false;
+//		}
+//		else
+//		{
+//			generation_key = font_effect->GetName() + ";" + font_effect->GetGenerationKey();
+//			FontLayerCache::iterator cache_iterator = layer_cache.find(generation_key);
+//			if (cache_iterator != layer_cache.end())
+//				clone = cache_iterator->second;
+//		}
+
+//		// Create a new layer.
+//		layer->Initialise(this, font_effect, clone, deep_clone);
+
+//		// Cache the layer in the layer cache if it generated its own textures (ie, didn't clone).
+//		if (clone == NULL)
+//			layer_cache[generation_key] = layer;
+//	}
+
+//	return layer;
+//}
+
+//}
+//}

+ 182 - 0
Source/Core/FreeType/FontFaceHandle.h

@@ -0,0 +1,182 @@
+///*
+// * This source file is part of libRocket, the HTML/CSS Interface Middleware
+// *
+// * For the latest information, see http://www.librocket.com
+// *
+// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a copy
+// * of this software and associated documentation files (the "Software"), to deal
+// * in the Software without restriction, including without limitation the rights
+// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// * copies of the Software, and to permit persons to whom the Software is
+// * furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included in
+// * all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// * THE SOFTWARE.
+// *
+// */
+
+//#ifndef ROCKETCOREFONTFACEHANDLE_H
+//#define ROCKETCOREFONTFACEHANDLE_H
+
+//#include "../../Include/Rocket/Core/ReferenceCountable.h"
+//#include "UnicodeRange.h"
+//#include "../../Include/Rocket/Core/Font.h"
+//#include "../../Include/Rocket/Core/FontEffect.h"
+//#include "../../Include/Rocket/Core/FontGlyph.h"
+//#include "../../Include/Rocket/Core/Geometry.h"
+//#include "../../Include/Rocket/Core/String.h"
+//#include "../../Include/Rocket/Core/Texture.h"
+//#include <ft2build.h>
+//#include FT_FREETYPE_H
+
+//namespace Rocket {
+//namespace Core {
+
+//class FontFaceLayer;
+
+///**
+//	@author Peter Curry
+// */
+
+//class FontFaceHandle : public ReferenceCountable
+//{
+//public:
+//	FontFaceHandle();
+//	virtual ~FontFaceHandle();
+
+//	/// Initialises the handle so it is able to render text.
+//	/// @param[in] ft_face The FreeType face that this handle is rendering.
+//	/// @param[in] charset The comma-separated list of unicode ranges this handle must support.
+//	/// @param[in] size The size, in points, of the face this handle should render at.
+//	/// @return True if the handle initialised successfully and is ready for rendering, false if an error occured.
+//	bool Initialise(FT_Face ft_face, const String& charset, int size);
+
+//	/// Returns the average advance of all glyphs in this font face.
+//	/// @return An approximate width of the characters in this font face.
+//	int GetCharacterWidth() const;
+
+//	/// Returns the point size of this font face.
+//	/// @return The face's point size.
+//	int GetSize() const;
+//	/// Returns the pixel height of a lower-case x in this font face.
+//	/// @return The height of a lower-case x.
+//	int GetXHeight() const;
+//	/// Returns the default height between this font face's baselines.
+//	/// @return The default line height.
+//	int GetLineHeight() const;
+
+//	/// Returns the font's baseline, as a pixel offset from the bottom of the font.
+//	/// @return The font's baseline.
+//	int GetBaseline() const;
+
+//	/// Returns the font's glyphs.
+//	/// @return The font's glyphs.
+//	const FontGlyphList& GetGlyphs() const;
+
+//	/// Returns the width a string will take up if rendered with this handle.
+//	/// @param[in] string The string to measure.
+//	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning.
+//	/// @return The width, in pixels, this string will occupy if rendered with this handle.
+//	int GetStringWidth(const WString& string, word prior_character = 0) const;
+
+//	/// Generates, if required, the layer configuration for a given array of font effects.
+//	/// @param[in] font_effects The list of font effects to generate the configuration for.
+//	/// @return The index to use when generating geometry using this configuration.
+//	int GenerateLayerConfiguration(FontEffectMap& font_effects);
+//	/// Generates the texture data for a layer (for the texture database).
+//	/// @param[out] texture_data The pointer to be set to the generated texture data.
+//	/// @param[out] texture_dimensions The dimensions of the texture.
+//	/// @param[in] layer_id The id of the layer to request the texture data from.
+//	/// @param[in] texture_id The index of the texture within the layer to generate.
+//	bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id);
+
+//	/// Generates the geometry required to render a single line of text.
+//	/// @param[out] geometry An array of geometries to generate the geometry into.
+//	/// @param[in] string The string to render.
+//	/// @param[in] position The position of the baseline of the first character to render.
+//	/// @param[in] colour The colour to render the text.
+//	/// @return The width, in pixels, of the string geometry.
+//	int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const;
+//	/// Generates the geometry required to render a line above, below or through a line of text.
+//	/// @param[out] geometry The geometry to append the newly created geometry into.
+//	/// @param[in] position The position of the baseline of the lined text.
+//	/// @param[in] width The width of the string to line.
+//	/// @param[in] height The height to render the line at.
+//	/// @param[in] colour The colour to draw the line in.
+//	void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const;
+
+//	/// Returns the font face's raw charset (the charset range as a string).
+//	/// @return The font face's charset.
+//	const String& GetRawCharset() const;
+//	/// Returns the font face's charset.
+//	/// @return The font face's charset.
+//	const UnicodeRangeList& GetCharset() const;
+
+//protected:
+//	/// Destroys the handle.
+//	virtual void OnReferenceDeactivate();
+
+//private:
+//	void GenerateMetrics(void);
+
+//	void BuildGlyphMap(const UnicodeRange& unicode_range);
+//	void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph);
+
+//	int GetKerning(word lhs, word rhs) const;
+
+//	// Generates (or shares) a layer derived from a font effect.
+//	FontFaceLayer* GenerateLayer(FontEffect* font_effect);
+
+//	typedef std::vector< int > GlyphKerningList;
+//	typedef std::vector< GlyphKerningList > FontKerningList;
+
+//	FT_Face ft_face;
+
+//	FontGlyphList glyphs;
+
+//	typedef std::map< const FontEffect*, FontFaceLayer* > FontLayerMap;
+//	typedef std::map< String, FontFaceLayer* > FontLayerCache;
+//	typedef std::vector< FontFaceLayer* > LayerConfiguration;
+//	typedef std::vector< LayerConfiguration > LayerConfigurationList;
+
+//	// The list of all font layers, index by the effect that instanced them.
+//	FontFaceLayer* base_layer;
+//	FontLayerMap layers;
+//	// Each font layer that generated geometry or textures, indexed by the respective generation
+//	// key.
+//	FontLayerCache layer_cache;
+
+//	// All configurations currently in use on this handle. New configurations will be generated as
+//	// required.
+//	LayerConfigurationList layer_configurations;
+
+//	// The average advance (in pixels) of all of this face's glyphs.
+//	int average_advance;
+
+//	int size;
+//	int x_height;
+//	int line_height;
+//	int baseline;
+
+//	float underline_position;
+//	float underline_thickness;
+
+//	String raw_charset;
+//	UnicodeRangeList charset;
+//	unsigned int max_codepoint;
+//};
+
+//}
+//}
+
+//#endif

+ 242 - 0
Source/Core/FreeType/FontFaceLayer.cpp

@@ -0,0 +1,242 @@
+///*
+// * This source file is part of libRocket, the HTML/CSS Interface Middleware
+// *
+// * For the latest information, see http://www.librocket.com
+// *
+// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a copy
+// * of this software and associated documentation files (the "Software"), to deal
+// * in the Software without restriction, including without limitation the rights
+// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// * copies of the Software, and to permit persons to whom the Software is
+// * furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included in
+// * all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// * THE SOFTWARE.
+// *
+// */
+
+//#include "precompiled.h"
+//#include "FontFaceLayer.h"
+//#include "../../Include/Rocket/Core/Core.h"
+//#include "FontFaceHandle.h"
+
+//namespace Rocket {
+//namespace Core {
+
+//FontFaceLayer::FontFaceLayer() : colour(255, 255, 255)
+//{
+//	handle = NULL;
+//	effect = NULL;
+//}
+
+//FontFaceLayer::~FontFaceLayer()
+//{
+//	if (effect != NULL)
+//		effect->RemoveReference();
+//}
+
+//// Generates the character and texture data for the layer.
+//bool FontFaceLayer::Initialise(const FontFaceHandle* _handle, FontEffect* _effect, const FontFaceLayer* clone, bool deep_clone)
+//{
+//	handle = _handle;
+//	effect = _effect;
+//	if (effect != NULL)
+//	{
+//		effect->AddReference();
+//		colour = effect->GetColour();
+//	}
+
+//	const FontGlyphList& glyphs = handle->GetGlyphs();
+
+//	// Clone the geometry and textures from the clone layer.
+//	if (clone != NULL)
+//	{
+//		// Copy the cloned layer's characters.
+//		characters = clone->characters;
+
+//		// Copy (and reference) the cloned layer's textures.
+//		for (size_t i = 0; i < clone->textures.size(); ++i)
+//			textures.push_back(clone->textures[i]);
+
+//		// Request the effect (if we have one) adjust the origins as appropriate.
+//		if (!deep_clone &&
+//			effect != NULL)
+//		{
+//			for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+//			{
+//				const FontGlyph& glyph = *i;
+
+//				if (glyph.character >= characters.size())
+//					continue;
+
+//				Character& character = characters[glyph.character];
+
+//				Vector2i glyph_origin(Math::RealToInteger(character.origin.x), Math::RealToInteger(character.origin.y));
+//				Vector2i glyph_dimensions(Math::RealToInteger(character.dimensions.x), Math::RealToInteger(character.dimensions.y));
+
+//				if (effect->GetGlyphMetrics(glyph_origin, glyph_dimensions, glyph))
+//				{
+//					character.origin.x = (float) glyph_origin.x;
+//					character.origin.y = (float) glyph_origin.y;
+//				}
+//				else
+//					character.texture_index = -1;
+//			}
+//		}
+//	}
+//	else
+//	{
+//		// Initialise the texture layout for the glyphs.
+//		characters.resize(glyphs.size(), Character());
+//		for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+//		{
+//			const FontGlyph& glyph = *i;
+
+//			Vector2i glyph_origin(0, 0);
+//			Vector2i glyph_dimensions = glyph.bitmap_dimensions;
+
+//			// Adjust glyph origin / dimensions for the font effect.
+//			if (effect != NULL)
+//			{
+//				if (!effect->GetGlyphMetrics(glyph_origin, glyph_dimensions, glyph))
+//					continue;
+//			}
+
+//			Character character;
+//			character.origin = Vector2f((float) (glyph_origin.x + glyph.bearing.x), (float) (glyph_origin.y - glyph.bearing.y));
+//			character.dimensions = Vector2f((float) glyph_dimensions.x - glyph_origin.x, (float) glyph_dimensions.y - glyph_origin.y);
+//			characters[glyph.character] = character;
+
+//			// Add the character's dimensions into the texture layout engine.
+//			texture_layout.AddRectangle(glyph.character, glyph_dimensions - glyph_origin);
+//		}
+
+//		// Generate the texture layout; this will position the glyph rectangles efficiently and
+//		// allocate the texture data ready for writing.
+//		if (!texture_layout.GenerateLayout(512))
+//			return false;
+
+
+//		// Iterate over each rectangle in the layout, copying the glyph data into the rectangle as
+//		// appropriate and generating geometry.
+//		for (int i = 0; i < texture_layout.GetNumRectangles(); ++i)
+//		{
+//			TextureLayoutRectangle& rectangle = texture_layout.GetRectangle(i);
+//			const TextureLayoutTexture& texture = texture_layout.GetTexture(rectangle.GetTextureIndex());
+//			Character& character = characters[(word) rectangle.GetId()];
+
+//			// Set the character's texture index.
+//			character.texture_index = rectangle.GetTextureIndex();
+
+//			// Generate the character's texture coordinates.
+//			character.texcoords[0].x = float(rectangle.GetPosition().x) / float(texture.GetDimensions().x);
+//			character.texcoords[0].y = float(rectangle.GetPosition().y) / float(texture.GetDimensions().y);
+//			character.texcoords[1].x = float(rectangle.GetPosition().x + rectangle.GetDimensions().x) / float(texture.GetDimensions().x);
+//			character.texcoords[1].y = float(rectangle.GetPosition().y + rectangle.GetDimensions().y) / float(texture.GetDimensions().y);
+//		}
+
+
+//		// Generate the textures.
+//		for (int i = 0; i < texture_layout.GetNumTextures(); ++i)
+//		{
+//			Texture texture;
+//			if (!texture.Load(String(64, "?font::%p/%p/%d", handle, effect, i)))
+//				return false;
+
+//			textures.push_back(texture);
+//		}
+//	}
+
+
+//	return true;
+//}
+
+//// Generates the texture data for a layer (for the texture database).
+//bool FontFaceLayer::GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id)
+//{
+//	if (texture_id < 0 ||
+//		texture_id > texture_layout.GetNumTextures())
+//		return false;
+
+//	const FontGlyphList& glyphs = handle->GetGlyphs();
+
+//	// Generate the texture data.
+//	texture_data = texture_layout.GetTexture(texture_id).AllocateTexture();
+//	texture_dimensions = texture_layout.GetTexture(texture_id).GetDimensions();
+
+//	for (int i = 0; i < texture_layout.GetNumRectangles(); ++i)
+//	{
+//		TextureLayoutRectangle& rectangle = texture_layout.GetRectangle(i);
+//		Character& character = characters[(word) rectangle.GetId()];
+
+//		if (character.texture_index != texture_id)
+//			continue;
+
+//		const FontGlyph& glyph = glyphs[rectangle.GetId()];
+
+//		if (effect == NULL)
+//		{
+//			// Copy the glyph's bitmap data into its allocated texture.
+//			if (glyph.bitmap_data != NULL)
+//			{
+//				byte* destination = rectangle.GetTextureData();
+//				byte* source = glyph.bitmap_data;
+
+//				for (int j = 0; j < glyph.bitmap_dimensions.y; ++j)
+//				{
+//					for (int k = 0; k < glyph.bitmap_dimensions.x; ++k)
+//						destination[k * 4 + 3] = source[k];
+
+//					destination += rectangle.GetTextureStride();
+//					source += glyph.bitmap_dimensions.x;
+//				}
+//			}
+//		}
+//		else
+//		{
+//			effect->GenerateGlyphTexture(rectangle.GetTextureData(), Vector2i(Math::RealToInteger(character.dimensions.x), Math::RealToInteger(character.dimensions.y)), rectangle.GetTextureStride(), glyph);
+//		}
+//	}
+
+//	return true;
+//}
+
+//// Returns the effect used to generate the layer.
+//const FontEffect* FontFaceLayer::GetFontEffect() const
+//{
+//	return effect;
+//}
+
+//// Returns on the layer's textures.
+//const Texture* FontFaceLayer::GetTexture(int index)
+//{
+//	ROCKET_ASSERT(index >= 0);
+//	ROCKET_ASSERT(index < GetNumTextures());
+
+//	return &(textures[index]);
+//}
+
+//// Returns the number of textures employed by this layer.
+//int FontFaceLayer::GetNumTextures() const
+//{
+//	return (int) textures.size();
+//}
+
+//// Returns the layer's colour.
+//const Colourb& FontFaceLayer::GetColour() const
+//{
+//	return colour;
+//}
+
+//}
+//}

+ 142 - 0
Source/Core/FreeType/FontFaceLayer.h

@@ -0,0 +1,142 @@
+///*
+// * This source file is part of libRocket, the HTML/CSS Interface Middleware
+// *
+// * For the latest information, see http://www.librocket.com
+// *
+// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a copy
+// * of this software and associated documentation files (the "Software"), to deal
+// * in the Software without restriction, including without limitation the rights
+// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// * copies of the Software, and to permit persons to whom the Software is
+// * furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included in
+// * all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// * THE SOFTWARE.
+// *
+// */
+
+//#ifndef ROCKETCOREFONTFACELAYER_H
+//#define ROCKETCOREFONTFACELAYER_H
+
+//#include "../../Include/Rocket/Core/FontGlyph.h"
+//#include "../../Include/Rocket/Core/Geometry.h"
+//#include "../../Include/Rocket/Core/GeometryUtilities.h"
+//#include "../../Include/Rocket/Core/String.h"
+//#include "../../Include/Rocket/Core/Texture.h"
+//#include "TextureLayout.h"
+
+//namespace Rocket {
+//namespace Core {
+
+//class FontEffect;
+//class FontFaceHandle;
+
+///**
+//	A textured layer stored as part of a font face handle. Each handle will have at least a base
+//	layer for the standard font. Further layers can be added to allow to rendering of text effects.
+
+//	@author Peter Curry
+// */
+
+//class FontFaceLayer
+//{
+//public:
+//	FontFaceLayer();
+//	~FontFaceLayer();
+
+//	/// Generates the character and texture data for the layer.
+//	/// @param[in] handle The handle generating this layer.
+//	/// @param[in] effect The effect to initialise the layer with.
+//	/// @param[in] clone The layer to optionally clone geometry and texture data from.
+//	/// @param[in] deep_clone If true, the clones geometry will be completely cloned and the effect will have no option to affect even the glyph origins.
+//	/// @return True if the layer was generated successfully, false if not.
+//	bool Initialise(const FontFaceHandle* handle, FontEffect* effect = NULL, const FontFaceLayer* clone = NULL, bool deep_clone = false);
+
+//	/// Generates the texture data for a layer (for the texture database).
+//	/// @param[out] texture_data The pointer to be set to the generated texture data.
+//	/// @param[out] texture_dimensions The dimensions of the texture.
+//	/// @param[in] glyphs The glyphs required by the font face handle.
+//	/// @param[in] texture_id The index of the texture within the layer to generate.
+//	bool GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id);
+//	/// Generates the geometry required to render a single character.
+//	/// @param[out] geometry An array of geometries this layer will write to. It must be at least as big as the number of textures in this layer.
+//	/// @param[in] character_code The character to generate geometry for.
+//	/// @param[in] position The position of the baseline.
+//	/// @param[in] colour The colour of the string.
+//	inline void GenerateGeometry(Geometry* geometry, const word character_code, const Vector2f& position, const Colourb& colour) const
+//	{
+//		if (character_code >= characters.size())
+//			return;
+
+//		const Character& character = characters[character_code];
+//		if (character.texture_index < 0)
+//			return;
+
+//		// Generate the geometry for the character.
+//		std::vector< Vertex >& character_vertices = geometry[character.texture_index].GetVertices();
+//		std::vector< int >& character_indices = geometry[character.texture_index].GetIndices();
+
+//		character_vertices.resize(character_vertices.size() + 4);
+//		character_indices.resize(character_indices.size() + 6);
+//		GeometryUtilities::GenerateQuad(&character_vertices[0] + (character_vertices.size() - 4), &character_indices[0] + (character_indices.size() - 6), Vector2f(position.x + character.origin.x, position.y + character.origin.y), character.dimensions, colour, character.texcoords[0], character.texcoords[1], (int)character_vertices.size() - 4);
+//	}
+
+//	/// Returns the effect used to generate the layer.
+//	/// @return The layer's effect.
+//	const FontEffect* GetFontEffect() const;
+
+//	/// Returns on the layer's textures.
+//	/// @param[in] index The index of the desired texture.
+//	/// @return The requested texture.
+//	const Texture* GetTexture(int index);
+//	/// Returns the number of textures employed by this layer.
+//	/// @return The number of used textures.
+//	int GetNumTextures() const;
+
+//	/// Returns the layer's colour.
+//	/// @return The layer's colour.
+//	const Colourb& GetColour() const;
+
+//private:
+//	struct Character
+//	{
+//		Character() : texture_index(-1) { }
+
+//		// The offset, in pixels, of the baseline from the start of this character's geometry.
+//		Vector2f origin;
+//		// The width and height, in pixels, of this character's geometry.
+//		Vector2f dimensions;
+//		// The texture coordinates for the character's geometry.
+//		Vector2f texcoords[2];
+
+//		// The texture this character renders from.
+//		int texture_index;
+//	};
+
+//	typedef std::vector< Character > CharacterList;
+//	typedef std::vector< Texture > TextureList;
+
+//	const FontFaceHandle* handle;
+//	FontEffect* effect;
+
+//	TextureLayout texture_layout;
+
+//	CharacterList characters;
+//	TextureList textures;
+//	Colourb colour;
+//};
+
+//}
+//}
+
+//#endif

+ 79 - 0
Source/Core/FreeType/FontFamily.cpp

@@ -0,0 +1,79 @@
+///*
+// * This source file is part of libRocket, the HTML/CSS Interface Middleware
+// *
+// * For the latest information, see http://www.librocket.com
+// *
+// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a copy
+// * of this software and associated documentation files (the "Software"), to deal
+// * in the Software without restriction, including without limitation the rights
+// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// * copies of the Software, and to permit persons to whom the Software is
+// * furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included in
+// * all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// * THE SOFTWARE.
+// *
+// */
+
+//#include "precompiled.h"
+//#include "FontFamily.h"
+//#include "FontFace.h"
+
+//namespace Rocket {
+//namespace Core {
+
+//FontFamily::FontFamily(const String& name) : name(name)
+//{
+//}
+
+//FontFamily::~FontFamily()
+//{
+//	for (size_t i = 0; i < font_faces.size(); ++i)
+//		delete font_faces[i];
+//}
+
+//// Adds a new face to the family.
+//bool FontFamily::AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream)
+//{
+//	FontFace* face = new FontFace(ft_face, style, weight, release_stream);
+//	font_faces.push_back(face);
+
+//	return true;
+//}
+
+//// Returns a handle to the most appropriate font in the family, at the correct size.
+//FontFaceHandle* FontFamily::GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size)
+//{
+//	// Search for a face of the same style, and match the weight as closely as we can.
+//	FontFace* matching_face = NULL;
+//	for (size_t i = 0; i < font_faces.size(); i++)
+//	{
+//		// If we've found a face matching the style, then ... great! We'll match it regardless of the weight. However,
+//		// if it's a perfect match, then we'll stop looking altogether.
+//		if (font_faces[i]->GetStyle() == style)
+//		{
+//			matching_face = font_faces[i];
+
+//			if (font_faces[i]->GetWeight() == weight)
+//				break;
+//		}
+//	}
+
+//	if (matching_face == NULL)
+//		return NULL;
+
+//	return matching_face->GetHandle(charset, size);
+//}
+
+//}
+//}

+ 81 - 0
Source/Core/FreeType/FontFamily.h

@@ -0,0 +1,81 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFREETYPEFONTFAMILY_H
+#define ROCKETCOREFREETYPEFONTFAMILY_H
+
+#include <Rocket/Core/Font.h>
+#include <Rocket/Core/FontFamily.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Rocket {
+namespace Core {
+
+class FontFace;
+class FontFaceHandle;
+
+/**
+    @author Peter Curry
+ */
+
+namespace FreeType {
+
+class FontFamily : public Rocket::Core::FontFamily
+{
+public:
+    FontFamily(const String& name);
+    ~FontFamily();
+
+    /// Adds a new face to the family.
+    /// @param[in] ft_face The previously loaded FreeType face.
+    /// @param[in] style The style of the new face.
+    /// @param[in] weight The weight of the new face.
+    /// @param[in] release_stream True if the application must free the face's memory stream.
+    /// @return True if the face was loaded successfully, false otherwise.
+    bool AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream);
+
+    /// Returns a handle to the most appropriate font in the family, at the correct size.
+    /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges.
+    /// @param[in] style The style of the desired handle.
+    /// @param[in] weight The weight of the desired handle.
+    /// @param[in] size The size of desired handle, in points.
+    /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise.
+    FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size);
+
+private:
+    String name;
+
+    typedef std::vector< FontFace* > FontFaceList;
+    FontFaceList font_faces;
+};
+
+}
+}
+}
+
+#endif

+ 267 - 0
Source/Core/FreeType/FontProvider.cpp

@@ -0,0 +1,267 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include <Rocket/Core/FreeType/FontProvider.h>
+#include "FontFaceHandle.h"
+#include <Rocket/Core/FontDatabase.h>
+#include "FontFamily.h"
+#include <Rocket/Core.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Rocket {
+namespace Core {
+namespace FreeType {
+
+FontProvider* FontProvider::instance = NULL;
+
+static FT_Library ft_library = NULL;
+
+FontProvider::FontProvider()
+{
+    ROCKET_ASSERT(instance == NULL);
+    instance = this;
+}
+
+FontProvider::~FontProvider()
+{
+    ROCKET_ASSERT(instance == this);
+    instance = NULL;
+}
+
+bool FontProvider::Initialise()
+{
+    if (instance == NULL)
+    {
+        new FontProvider();
+
+        FT_Error result = FT_Init_FreeType(&ft_library);
+        if (result != 0)
+        {
+            Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result);
+            Shutdown();
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void FontProvider::Shutdown()
+{
+    if (instance != NULL)
+    {
+        for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i)
+            delete (*i).second;
+
+        if (ft_library != NULL)
+        {
+            FT_Done_FreeType(ft_library);
+            ft_library = NULL;
+        }
+
+        delete instance;
+    }
+}
+
+// Loads a new font face.
+bool FontProvider::LoadFontFace(const String& file_name)
+{
+    FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
+    if (ft_face == NULL)
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+        return false;
+    }
+
+    Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
+    Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+
+    if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true))
+    {
+        Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+        return true;
+    }
+    else
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+        return false;
+    }
+}
+
+// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
+bool FontProvider::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight)
+{
+    FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
+    if (ft_face == NULL)
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+        return false;
+    }
+
+    if (instance->AddFace(ft_face, family, style, weight, true))
+    {
+        Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+        return true;
+    }
+    else
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+        return false;
+    }
+}
+
+// Adds a new font face to the database, loading from memory.
+bool FontProvider::LoadFontFace(const byte* data, int data_length)
+{
+    FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
+    if (ft_face == NULL)
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
+        return false;
+    }
+
+    Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
+    Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+
+    if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false))
+    {
+        Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+        return true;
+    }
+    else
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+        return false;
+    }
+}
+
+// Adds a new font face to the database, loading from memory, ignoring any family, style and weight information stored in the face itself.
+bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
+{
+    FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
+    if (ft_face == NULL)
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
+        return false;
+    }
+
+    if (instance->AddFace(ft_face, family, style, weight, false))
+    {
+        Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+        return true;
+    }
+    else
+    {
+        Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+        return false;
+    }
+}
+
+// Returns a handle to a font face that can be used to position and render text.
+Rocket::Core::FontFaceHandle* FontProvider::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size)
+{
+    FontFamilyMap::iterator iterator = instance->font_families.find(family);
+    if (iterator == instance->font_families.end())
+        return NULL;
+
+    return (*iterator).second->GetFaceHandle(charset, style, weight, size);
+}
+
+
+// Adds a loaded face to the appropriate font family.
+bool FontProvider::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream)
+{
+    Rocket::Core::FontFamily* font_family = NULL;
+    FontFamilyMap::iterator iterator = instance->font_families.find(family);
+    if (iterator != instance->font_families.end())
+        font_family = (*iterator).second;
+    else
+    {
+        font_family = new FontFamily(family);
+        instance->font_families[family] = font_family;
+    }
+
+    return font_family->AddFace((FT_Face) face, style, weight, release_stream);
+}
+
+// Loads a FreeType face.
+void* FontProvider::LoadFace(const String& file_name)
+{
+    FileInterface* file_interface = GetFileInterface();
+    FileHandle handle = file_interface->Open(file_name);
+
+    if (!handle)
+    {
+        return NULL;
+    }
+
+    size_t length = file_interface->Length(handle);
+
+    FT_Byte* buffer = new FT_Byte[length];
+    file_interface->Read(buffer, length, handle);
+    file_interface->Close(handle);
+
+    return LoadFace(buffer, (int)length, file_name, true);
+}
+
+// Loads a FreeType face from memory.
+void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data)
+{
+    FT_Face face = NULL;
+    int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face);
+    if (error != 0)
+    {
+        Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString());
+        if (local_data)
+            delete[] data;
+
+        return NULL;
+    }
+
+    // Initialise the character mapping on the face.
+    if (face->charmap == NULL)
+    {
+        FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN);
+        if (face->charmap == NULL)
+        {
+            Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString());
+            FT_Done_Face(face);
+            if (local_data)
+                delete[] data;
+
+            return NULL;
+        }
+    }
+
+    return face;
+}
+
+}
+}
+}

+ 2 - 2
Source/Debugger/Plugin.cpp

@@ -286,8 +286,8 @@ Plugin* Plugin::GetInstance()
 
 bool Plugin::LoadFont()
 {
-	return (Core::FontDatabase::LoadFontFace(lacuna_regular, sizeof(lacuna_regular) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_NORMAL, Core::Font::WEIGHT_NORMAL) &&
-			Core::FontDatabase::LoadFontFace(lacuna_italic, sizeof(lacuna_italic) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_ITALIC, Core::Font::WEIGHT_NORMAL));
+    return (Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_regular, sizeof(lacuna_regular) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_NORMAL, Core::Font::WEIGHT_NORMAL) &&
+            Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_italic, sizeof(lacuna_italic) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_ITALIC, Core::Font::WEIGHT_NORMAL));
 }
 
 bool Plugin::LoadMenuElement()