Browse Source

Merge pull request #267 from konopka90/master

New font provider - loading bitmap fonts
Tom Mason 10 years ago
parent
commit
cbbbed70a8
41 changed files with 3709 additions and 534 deletions
  1. 1 1
      Build/CMakeLists.txt
  2. 25 2
      Build/cmake/FileList.cmake
  3. 7 0
      Build/cmake/SampleFileList.cmake
  4. 101 0
      Include/Rocket/Core/BitmapFont/FontProvider.h
  5. 17 10
      Include/Rocket/Core/FontDatabase.h
  6. 6 9
      Include/Rocket/Core/FontFace.h
  7. 6 7
      Include/Rocket/Core/FontFamily.h
  8. 70 0
      Include/Rocket/Core/FontProvider.h
  9. 101 0
      Include/Rocket/Core/FreeType/FontProvider.h
  10. 270 0
      Samples/assets/Arial.fnt
  11. BIN
      Samples/assets/Arial_0.tga
  12. 28 0
      Samples/assets/bitmapfont.rml
  13. 130 0
      Samples/basic/bitmapfont/src/main.cpp
  14. 147 0
      Source/Core/BitmapFont/BitmapFontDefinitions.h
  15. 130 0
      Source/Core/BitmapFont/FontFace.cpp
  16. 68 0
      Source/Core/BitmapFont/FontFace.h
  17. 428 0
      Source/Core/BitmapFont/FontFaceHandle.cpp
  18. 136 0
      Source/Core/BitmapFont/FontFaceHandle.h
  19. 127 0
      Source/Core/BitmapFont/FontFaceLayer.cpp
  20. 78 0
      Source/Core/BitmapFont/FontFaceLayer.h
  21. 55 0
      Source/Core/BitmapFont/FontFamily.cpp
  22. 66 0
      Source/Core/BitmapFont/FontFamily.h
  23. 112 0
      Source/Core/BitmapFont/FontParser.cpp
  24. 68 0
      Source/Core/BitmapFont/FontParser.h
  25. 208 0
      Source/Core/BitmapFont/FontProvider.cpp
  26. 94 158
      Source/Core/FontDatabase.cpp
  27. 2 95
      Source/Core/FontFace.cpp
  28. 0 209
      Source/Core/FontFaceHandle.cpp
  29. 7 26
      Source/Core/FontFaceHandle.h
  30. 3 3
      Source/Core/FontFaceLayer.h
  31. 2 11
      Source/Core/FontFamily.cpp
  32. 45 0
      Source/Core/FontProvider.cpp
  33. 139 0
      Source/Core/FreeType/FontFace.cpp
  34. 68 0
      Source/Core/FreeType/FontFace.h
  35. 458 0
      Source/Core/FreeType/FontFaceHandle.cpp
  36. 117 0
      Source/Core/FreeType/FontFaceHandle.h
  37. 58 0
      Source/Core/FreeType/FontFamily.cpp
  38. 67 0
      Source/Core/FreeType/FontFamily.h
  39. 258 0
      Source/Core/FreeType/FontProvider.cpp
  40. 4 1
      Source/Core/TextureLayoutTexture.cpp
  41. 2 2
      Source/Debugger/Plugin.cpp

+ 1 - 1
Build/CMakeLists.txt

@@ -468,7 +468,7 @@ endmacro()
 if(BUILD_SAMPLES)
     include(SampleFileList)
 
-    set(samples treeview customlog drag loaddocument)
+    set(samples treeview customlog drag loaddocument bitmapfont)
     set(tutorials template datagrid datagrid_tree tutorial_drag)
     
 if(NOT BUILD_FRAMEWORK)

+ 25 - 2
Build/cmake/FileList.cmake

@@ -36,10 +36,17 @@ set(Core_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectOutlineInstancer.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectShadow.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectShadowInstancer.h
-    ${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/FontFamily.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/BitmapFontDefinitions.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontParser.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFace.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceHandle.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceLayer.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/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 +135,12 @@ 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/FontFace.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/BitmapFont/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 +245,17 @@ 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/FontFamily.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontProvider.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontParser.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFace.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceHandle.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceLayer.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFamily.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontProvider.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/Geometry.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryDatabase.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryUtilities.cpp

+ 7 - 0
Build/cmake/SampleFileList.cmake

@@ -45,6 +45,13 @@ set(loaddocument_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Samples/basic/loaddocument/src/main.cpp
 )
 
+set(bitmapfont_HDR_FILES
+)
+
+set(bitmapfont_SRC_FILES
+    ${PROJECT_SOURCE_DIR}/Samples/basic/bitmapfont/src/main.cpp
+)
+
 set(ogre3d_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Samples/basic/ogre3d/src/RenderInterfaceOgre3D.h
     ${PROJECT_SOURCE_DIR}/Samples/basic/ogre3d/src/RocketApplication.h

+ 101 - 0
Include/Rocket/Core/BitmapFont/FontProvider.h

@@ -0,0 +1,101 @@
+/*
+ * 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 ROCKETCOREBITMAPFONTFONTPROVIDER_H
+#define ROCKETCOREBITMAPFONTFONTPROVIDER_H
+
+#include "../StringUtilities.h"
+#include "../Font.h"
+#include "../FontProvider.h"
+
+namespace Rocket {
+namespace Core {
+
+
+class FontEffect;
+class FontFaceHandle;
+class PropertyDictionary;
+
+namespace BitmapFont {
+
+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);
+
+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

+ 17 - 10
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,
+        BitmapFont
+    };
+
 	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,19 @@ 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);
+    static FontProviderType GetFontProviderType(const String& file_name);
 
-	typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap;
-	FontFamilyMap font_families;
+    typedef std::vector< FontProvider *> FontProviderTable;
 
+    static FontProviderTable font_provider_table;
 	static FontDatabase* instance;
 };
 

+ 6 - 9
Source/Core/FontFace.h → Include/Rocket/Core/FontFace.h

@@ -28,9 +28,7 @@
 #ifndef ROCKETCOREFONTFACE_H
 #define ROCKETCOREFONTFACE_H
 
-#include "../../Include/Rocket/Core/Font.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include "Font.h"
 
 namespace Rocket {
 namespace Core {
@@ -44,8 +42,8 @@ class FontFaceHandle;
 class FontFace
 {
 public:
-	FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream);
-	~FontFace();
+    FontFace(Font::Style style, Font::Weight weight, bool release_stream);
+    virtual ~FontFace();
 
 	/// Returns the style of the font face.
 	/// @return The font face's style.
@@ -58,14 +56,13 @@ public:
 	/// @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);
+    virtual FontFaceHandle* GetHandle(const String& charset, int size) = 0;
 
 	/// 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();
+    virtual void ReleaseFace() = 0;
 
-private:
-	FT_Face face;
+protected:
 	Font::Style style;
 	Font::Weight weight;
 

+ 6 - 7
Source/Core/FontFamily.h → Include/Rocket/Core/FontFamily.h

@@ -28,9 +28,8 @@
 #ifndef ROCKETCOREFONTFAMILY_H
 #define ROCKETCOREFONTFAMILY_H
 
-#include "../../Include/Rocket/Core/Font.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include <Rocket/Core/StringUtilities.h>
+#include "Font.h"
 
 namespace Rocket {
 namespace Core {
@@ -46,7 +45,7 @@ class FontFamily
 {
 public:
 	FontFamily(const String& name);
-	~FontFamily();
+    virtual ~FontFamily();
 
 	/// Adds a new face to the family.
 	/// @param[in] ft_face The previously loaded FreeType face.
@@ -54,7 +53,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);
+    virtual bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream) = 0;
 
 	/// 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.
@@ -62,9 +61,9 @@ public:
 	/// @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);
+    FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size);
 
-private:
+protected:
 	String name;
 
 	typedef std::vector< FontFace* > FontFaceList;

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

@@ -0,0 +1,70 @@
+/*
+ * 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.
+    FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size);
+
+protected:
+
+    typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap;
+    FontFamilyMap font_families;
+};
+
+}
+}
+
+#endif

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

@@ -0,0 +1,101 @@
+/*
+ * 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 "../StringUtilities.h"
+#include "../Font.h"
+#include "../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);
+
+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

+ 270 - 0
Samples/assets/Arial.fnt

@@ -0,0 +1,270 @@
+<?xml version="1.0"?>
+<font>
+  <info face="Arial" size="26" bold="0" italic="0" src="Arial_0.tga"/>
+  <common lineHeight="26" base="26" scaleW="1024" scaleH="1024" />
+  <chars count="191">
+    <char id="32" x="170" y="40" width="1" height="1" xoffset="0" yoffset="21" xadvance="6" />
+    <char id="33" x="643" y="19" width="2" height="17" xoffset="3" yoffset="4" xadvance="8" />
+    <char id="34" x="63" y="41" width="6" height="6" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="35" x="84" y="23" width="13" height="17" xoffset="0" yoffset="4" xadvance="13" />
+    <char id="36" x="511" y="0" width="11" height="20" xoffset="1" yoffset="3" xadvance="13" />
+    <char id="37" x="724" y="0" width="18" height="17" xoffset="1" yoffset="4" xadvance="20" />
+    <char id="38" x="56" y="23" width="13" height="17" xoffset="1" yoffset="4" xadvance="15" />
+    <char id="39" x="77" y="41" width="2" height="6" xoffset="1" yoffset="4" xadvance="4" />
+    <char id="40" x="91" y="0" width="5" height="22" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="41" x="97" y="0" width="5" height="22" xoffset="2" yoffset="4" xadvance="8" />
+    <char id="42" x="54" y="41" width="8" height="7" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="43" x="916" y="18" width="12" height="12" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="44" x="80" y="41" width="2" height="5" xoffset="2" yoffset="19" xadvance="6" />
+    <char id="45" x="149" y="40" width="7" height="2" xoffset="0" yoffset="14" xadvance="8" />
+    <char id="46" x="167" y="40" width="2" height="2" xoffset="2" yoffset="19" xadvance="6" />
+    <char id="47" x="604" y="19" width="7" height="17" xoffset="0" yoffset="4" xadvance="6" />
+    <char id="48" x="273" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="49" x="620" y="19" width="6" height="17" xoffset="3" yoffset="4" xadvance="13" />
+    <char id="50" x="285" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="51" x="345" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="52" x="441" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="53" x="453" y="21" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="54" x="189" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="55" x="261" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="56" x="201" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="57" x="213" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="58" x="913" y="18" width="2" height="13" xoffset="2" yoffset="8" xadvance="6" />
+    <char id="59" x="717" y="18" width="2" height="16" xoffset="2" yoffset="8" xadvance="6" />
+    <char id="60" x="941" y="18" width="10" height="11" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="61" x="32" y="41" width="10" height="7" xoffset="1" yoffset="9" xadvance="13" />
+    <char id="62" x="952" y="18" width="10" height="11" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="63" x="225" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="64" x="0" y="0" width="21" height="22" xoffset="1" yoffset="4" xadvance="23" />
+    <char id="65" x="816" y="0" width="17" height="17" xoffset="-1" yoffset="4" xadvance="15" />
+    <char id="66" x="124" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="67" x="919" y="0" width="15" height="17" xoffset="1" yoffset="4" xadvance="17" />
+    <char id="68" x="951" y="0" width="14" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="69" x="163" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="70" x="237" y="22" width="11" height="17" xoffset="2" yoffset="4" xadvance="14" />
+    <char id="71" x="869" y="0" width="16" height="17" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="72" x="42" y="23" width="13" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="73" x="640" y="19" width="2" height="17" xoffset="2" yoffset="4" xadvance="6" />
+    <char id="74" x="576" y="19" width="9" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="75" x="996" y="0" width="14" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="76" x="543" y="19" width="10" height="17" xoffset="2" yoffset="4" xadvance="13" />
+    <char id="77" x="935" y="0" width="15" height="17" xoffset="2" yoffset="4" xadvance="19" />
+    <char id="78" x="70" y="23" width="13" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="79" x="852" y="0" width="16" height="17" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="80" x="98" y="23" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="81" x="560" y="0" width="16" height="18" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="82" x="981" y="0" width="14" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="83" x="28" y="23" width="13" height="17" xoffset="1" yoffset="4" xadvance="15" />
+    <char id="84" x="1011" y="0" width="12" height="17" xoffset="1" yoffset="4" xadvance="14" />
+    <char id="85" x="14" y="23" width="13" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="86" x="798" y="0" width="17" height="17" xoffset="-1" yoffset="4" xadvance="15" />
+    <char id="87" x="657" y="0" width="23" height="17" xoffset="0" yoffset="4" xadvance="23" />
+    <char id="88" x="903" y="0" width="15" height="17" xoffset="0" yoffset="4" xadvance="15" />
+    <char id="89" x="966" y="0" width="14" height="17" xoffset="0" yoffset="4" xadvance="14" />
+    <char id="90" x="0" y="23" width="13" height="17" xoffset="0" yoffset="4" xadvance="14" />
+    <char id="91" x="108" y="0" width="4" height="22" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="92" x="612" y="19" width="7" height="17" xoffset="0" yoffset="4" xadvance="6" />
+    <char id="93" x="103" y="0" width="4" height="22" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="94" x="983" y="18" width="10" height="9" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="95" x="111" y="41" width="14" height="2" xoffset="-1" yoffset="24" xadvance="13" />
+    <char id="96" x="106" y="41" width="4" height="3" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="97" x="814" y="18" width="11" height="13" xoffset="1" yoffset="8" xadvance="13" />
+    <char id="98" x="477" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="99" x="850" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="100" x="565" y="19" width="10" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="101" x="826" y="18" width="11" height="13" xoffset="1" yoffset="8" xadvance="13" />
+    <char id="102" x="595" y="19" width="8" height="17" xoffset="0" yoffset="4" xadvance="7" />
+    <char id="103" x="614" y="0" width="10" height="18" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="104" x="554" y="19" width="10" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="105" x="637" y="19" width="2" height="17" xoffset="1" yoffset="4" xadvance="5" />
+    <char id="106" x="85" y="0" width="5" height="22" xoffset="-2" yoffset="4" xadvance="4" />
+    <char id="107" x="249" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="11" />
+    <char id="108" x="646" y="19" width="2" height="17" xoffset="1" yoffset="4" xadvance="4" />
+    <char id="109" x="771" y="18" width="16" height="13" xoffset="1" yoffset="8" xadvance="18" />
+    <char id="110" x="894" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="111" x="802" y="18" width="11" height="13" xoffset="1" yoffset="8" xadvance="13" />
+    <char id="112" x="636" y="0" width="10" height="18" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="113" x="591" y="0" width="11" height="18" xoffset="0" yoffset="8" xadvance="12" />
+    <char id="114" x="905" y="18" width="7" height="13" xoffset="1" yoffset="8" xadvance="8" />
+    <char id="115" x="883" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="116" x="647" y="0" width="6" height="18" xoffset="0" yoffset="3" xadvance="6" />
+    <char id="117" x="861" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="118" x="788" y="18" width="13" height="13" xoffset="-1" yoffset="8" xadvance="11" />
+    <char id="119" x="753" y="18" width="17" height="13" xoffset="-1" yoffset="8" xadvance="15" />
+    <char id="120" x="838" y="18" width="11" height="13" xoffset="0" yoffset="8" xadvance="11" />
+    <char id="121" x="577" y="0" width="13" height="18" xoffset="-1" yoffset="8" xadvance="11" />
+    <char id="122" x="872" y="18" width="10" height="13" xoffset="0" yoffset="8" xadvance="11" />
+    <char id="123" x="71" y="0" width="6" height="22" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="124" x="113" y="0" width="2" height="22" xoffset="2" yoffset="4" xadvance="6" />
+    <char id="125" x="78" y="0" width="6" height="22" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="126" x="83" y="41" width="11" height="4" xoffset="1" yoffset="11" xadvance="13" />
+    <char id="160" x="172" y="40" width="1" height="1" xoffset="0" yoffset="21" xadvance="6" />
+    <char id="161" x="654" y="0" width="2" height="18" xoffset="3" yoffset="8" xadvance="8" />
+    <char id="162" x="60" y="0" width="10" height="22" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="163" x="111" y="23" width="12" height="17" xoffset="0" yoffset="4" xadvance="13" />
+    <char id="164" x="929" y="18" width="11" height="11" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="165" x="176" y="22" width="12" height="17" xoffset="0" yoffset="4" xadvance="13" />
+    <char id="166" x="116" y="0" width="2" height="22" xoffset="2" yoffset="4" xadvance="6" />
+    <char id="167" x="48" y="0" width="11" height="22" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="168" x="157" y="40" width="6" height="2" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="169" x="762" y="0" width="17" height="17" xoffset="0" yoffset="4" xadvance="17" />
+    <char id="170" x="8" y="41" width="7" height="8" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="171" x="973" y="18" width="9" height="10" xoffset="1" yoffset="10" xadvance="13" />
+    <char id="172" x="43" y="41" width="10" height="7" xoffset="1" yoffset="9" xadvance="13" />
+    <char id="173" x="141" y="40" width="7" height="2" xoffset="0" yoffset="14" xadvance="8" />
+    <char id="174" x="834" y="0" width="17" height="17" xoffset="0" yoffset="4" xadvance="17" />
+    <char id="175" x="126" y="40" width="14" height="2" xoffset="-1" yoffset="1" xadvance="13" />
+    <char id="176" x="70" y="41" width="6" height="6" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="177" x="720" y="18" width="12" height="14" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="178" x="16" y="41" width="7" height="8" xoffset="0" yoffset="4" xadvance="8" />
+    <char id="179" x="0" y="41" width="7" height="8" xoffset="0" yoffset="4" xadvance="8" />
+    <char id="180" x="101" y="41" width="4" height="3" xoffset="3" yoffset="4" xadvance="8" />
+    <char id="181" x="603" y="0" width="10" height="18" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="182" x="378" y="0" width="12" height="21" xoffset="0" yoffset="4" xadvance="12" />
+    <char id="183" x="164" y="40" width="2" height="2" xoffset="3" yoffset="12" xadvance="8" />
+    <char id="184" x="95" y="41" width="5" height="4" xoffset="1" yoffset="21" xadvance="8" />
+    <char id="185" x="1017" y="18" width="5" height="8" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="186" x="24" y="41" width="7" height="8" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="187" x="963" y="18" width="9" height="10" xoffset="3" yoffset="10" xadvance="13" />
+    <char id="188" x="705" y="0" width="18" height="17" xoffset="1" yoffset="4" xadvance="19" />
+    <char id="189" x="780" y="0" width="17" height="17" xoffset="1" yoffset="4" xadvance="19" />
+    <char id="190" x="743" y="0" width="18" height="17" xoffset="0" yoffset="4" xadvance="19" />
+    <char id="191" x="625" y="0" width="10" height="18" xoffset="2" yoffset="8" xadvance="14" />
+    <char id="192" x="137" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="193" x="173" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="194" x="191" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="195" x="155" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="196" x="449" y="0" width="17" height="20" xoffset="-1" yoffset="1" xadvance="15" />
+    <char id="197" x="119" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="198" x="681" y="0" width="23" height="17" xoffset="-1" yoffset="4" xadvance="23" />
+    <char id="199" x="277" y="0" width="15" height="21" xoffset="1" yoffset="4" xadvance="17" />
+    <char id="200" x="404" y="0" width="12" height="21" xoffset="2" yoffset="0" xadvance="15" />
+    <char id="201" x="391" y="0" width="12" height="21" xoffset="2" yoffset="0" xadvance="15" />
+    <char id="202" x="417" y="0" width="12" height="21" xoffset="2" yoffset="0" xadvance="15" />
+    <char id="203" x="498" y="0" width="12" height="20" xoffset="2" yoffset="1" xadvance="15" />
+    <char id="204" x="444" y="0" width="4" height="21" xoffset="1" yoffset="0" xadvance="6" />
+    <char id="205" x="439" y="0" width="4" height="21" xoffset="1" yoffset="0" xadvance="6" />
+    <char id="206" x="430" y="0" width="8" height="21" xoffset="-1" yoffset="0" xadvance="6" />
+    <char id="207" x="523" y="0" width="6" height="20" xoffset="0" yoffset="1" xadvance="6" />
+    <char id="208" x="886" y="0" width="16" height="17" xoffset="0" yoffset="4" xadvance="17" />
+    <char id="209" x="364" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="210" x="209" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="211" x="260" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="212" x="243" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="213" x="226" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="214" x="467" y="0" width="16" height="20" xoffset="1" yoffset="1" xadvance="18" />
+    <char id="215" x="994" y="18" width="9" height="9" xoffset="2" yoffset="8" xadvance="13" />
+    <char id="216" x="542" y="0" width="17" height="18" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="217" x="350" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="218" x="336" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="219" x="322" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="220" x="484" y="0" width="13" height="20" xoffset="2" yoffset="1" xadvance="17" />
+    <char id="221" x="293" y="0" width="14" height="21" xoffset="0" yoffset="0" xadvance="15" />
+    <char id="222" x="137" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="223" x="150" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="14" />
+    <char id="224" x="297" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="225" x="309" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="226" x="321" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="227" x="333" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="228" x="675" y="18" width="11" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="229" x="530" y="0" width="11" height="19" xoffset="1" yoffset="2" xadvance="13" />
+    <char id="230" x="733" y="18" width="19" height="13" xoffset="1" yoffset="8" xadvance="20" />
+    <char id="231" x="488" y="21" width="10" height="17" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="232" x="465" y="21" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="233" x="357" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="234" x="369" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="235" x="663" y="18" width="11" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="236" x="627" y="19" width="4" height="17" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="237" x="632" y="19" width="4" height="17" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="238" x="586" y="19" width="8" height="17" xoffset="-1" yoffset="4" xadvance="6" />
+    <char id="239" x="710" y="18" width="6" height="16" xoffset="0" yoffset="5" xadvance="6" />
+    <char id="240" x="381" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="241" x="510" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="242" x="393" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="243" x="405" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="244" x="417" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="245" x="429" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="246" x="687" y="18" width="11" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="247" x="1004" y="18" width="12" height="8" xoffset="1" yoffset="9" xadvance="13" />
+    <char id="248" x="649" y="19" width="13" height="16" xoffset="0" yoffset="6" xadvance="13" />
+    <char id="249" x="532" y="20" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="250" x="521" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="251" x="499" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="252" x="699" y="18" width="10" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="253" x="22" y="0" width="13" height="22" xoffset="-1" yoffset="4" xadvance="12" />
+    <char id="254" x="36" y="0" width="11" height="22" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="255" x="308" y="0" width="13" height="21" xoffset="-1" yoffset="5" xadvance="12" />
+  </chars>
+  <kernings count="70">
+    <kerning first="32" second="65" amount="-1" />
+    <kerning first="49" second="49" amount="-2" />
+    <kerning first="65" second="32" amount="-1" />
+    <kerning first="65" second="84" amount="-2" />
+    <kerning first="65" second="86" amount="-2" />
+    <kerning first="65" second="87" amount="-1" />
+    <kerning first="65" second="89" amount="-2" />
+    <kerning first="70" second="44" amount="-3" />
+    <kerning first="70" second="46" amount="-3" />
+    <kerning first="70" second="65" amount="-1" />
+    <kerning first="76" second="32" amount="-1" />
+    <kerning first="76" second="84" amount="-2" />
+    <kerning first="76" second="86" amount="-2" />
+    <kerning first="76" second="87" amount="-2" />
+    <kerning first="76" second="89" amount="-2" />
+    <kerning first="76" second="121" amount="-1" />
+    <kerning first="80" second="44" amount="-3" />
+    <kerning first="80" second="46" amount="-3" />
+    <kerning first="80" second="65" amount="-2" />
+    <kerning first="84" second="44" amount="-3" />
+    <kerning first="84" second="45" amount="-1" />
+    <kerning first="84" second="46" amount="-3" />
+    <kerning first="84" second="58" amount="-3" />
+    <kerning first="84" second="65" amount="-2" />
+    <kerning first="84" second="97" amount="-3" />
+    <kerning first="84" second="99" amount="-3" />
+    <kerning first="84" second="101" amount="-3" />
+    <kerning first="84" second="105" amount="-1" />
+    <kerning first="84" second="111" amount="-3" />
+    <kerning first="84" second="114" amount="-1" />
+    <kerning first="84" second="115" amount="-3" />
+    <kerning first="84" second="117" amount="-1" />
+    <kerning first="84" second="119" amount="-1" />
+    <kerning first="84" second="121" amount="-1" />
+    <kerning first="86" second="44" amount="-2" />
+    <kerning first="86" second="45" amount="-1" />
+    <kerning first="86" second="46" amount="-2" />
+    <kerning first="86" second="58" amount="-1" />
+    <kerning first="86" second="65" amount="-2" />
+    <kerning first="86" second="97" amount="-2" />
+    <kerning first="86" second="101" amount="-1" />
+    <kerning first="86" second="111" amount="-1" />
+    <kerning first="86" second="114" amount="-1" />
+    <kerning first="86" second="117" amount="-1" />
+    <kerning first="86" second="121" amount="-1" />
+    <kerning first="87" second="44" amount="-1" />
+    <kerning first="87" second="46" amount="-1" />
+    <kerning first="87" second="65" amount="-1" />
+    <kerning first="87" second="97" amount="-1" />
+    <kerning first="89" second="44" amount="-3" />
+    <kerning first="89" second="45" amount="-2" />
+    <kerning first="89" second="46" amount="-3" />
+    <kerning first="89" second="58" amount="-1" />
+    <kerning first="89" second="65" amount="-2" />
+    <kerning first="89" second="97" amount="-2" />
+    <kerning first="89" second="101" amount="-2" />
+    <kerning first="89" second="105" amount="-1" />
+    <kerning first="89" second="111" amount="-2" />
+    <kerning first="89" second="112" amount="-2" />
+    <kerning first="89" second="113" amount="-2" />
+    <kerning first="89" second="117" amount="-1" />
+    <kerning first="89" second="118" amount="-1" />
+    <kerning first="114" second="44" amount="-1" />
+    <kerning first="114" second="46" amount="-1" />
+    <kerning first="118" second="44" amount="-2" />
+    <kerning first="118" second="46" amount="-2" />
+    <kerning first="119" second="44" amount="-1" />
+    <kerning first="119" second="46" amount="-1" />
+    <kerning first="121" second="44" amount="-2" />
+    <kerning first="121" second="46" amount="-2" />
+  </kernings>
+</font>

BIN
Samples/assets/Arial_0.tga


+ 28 - 0
Samples/assets/bitmapfont.rml

@@ -0,0 +1,28 @@
+<rml>
+	<head>
+		<title>Demo</title>
+		<link type="text/template" href="window.rml" />
+		<style>
+			body
+			{
+				width: 300px;
+				height: 225px;
+				font-family: Arial;
+				margin: auto;
+			}
+			
+			div#title_bar div#icon
+			{
+				display: none;
+			}
+			
+			div#content
+			{
+				text-align: left;
+			}
+		</style>
+	</head>
+	<body template="window">
+		This is a bitmap font<br/>sample.
+	</body>
+</rml>

+ 130 - 0
Samples/basic/bitmapfont/src/main.cpp

@@ -0,0 +1,130 @@
+/*
+ * 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.h>
+#include <Rocket/Debugger.h>
+#include <Input.h>
+#include <Shell.h>
+
+Rocket::Core::Context* context = NULL;
+
+ShellRenderInterfaceExtensions *shell_renderer;
+
+void GameLoop()
+{
+	context->Update();
+
+	shell_renderer->PrepareRenderBuffer();
+	context->Render();
+	shell_renderer->PresentRenderBuffer();
+}
+
+#if defined ROCKET_PLATFORM_WIN32
+#include <windows.h>
+int APIENTRY WinMain(HINSTANCE ROCKET_UNUSED_PARAMETER(instance_handle), HINSTANCE ROCKET_UNUSED_PARAMETER(previous_instance_handle), char* ROCKET_UNUSED_PARAMETER(command_line), int ROCKET_UNUSED_PARAMETER(command_show))
+#else
+int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv))
+#endif
+{
+#ifdef ROCKET_PLATFORM_WIN32
+	ROCKET_UNUSED(instance_handle);
+	ROCKET_UNUSED(previous_instance_handle);
+	ROCKET_UNUSED(command_line);
+	ROCKET_UNUSED(command_show);
+#else
+	ROCKET_UNUSED(argc);
+	ROCKET_UNUSED(argv);
+#endif
+
+#ifdef ROCKET_PLATFORM_LINUX
+#define APP_PATH "../Samples/basic/loaddocument/"
+#else
+#define APP_PATH "../../Samples/basic/loaddocument/"
+#endif
+
+#ifdef ROCKET_PLATFORM_WIN32
+        DoAllocConsole();
+#endif
+
+        int window_width = 1024;
+        int window_height = 768;
+
+	ShellRenderInterfaceOpenGL opengl_renderer;
+	shell_renderer = &opengl_renderer;
+
+	// Generic OS initialisation, creates a window and attaches OpenGL.
+	if (!Shell::Initialise(APP_PATH) ||
+		!Shell::OpenWindow("Load Document Sample", shell_renderer, window_width, window_height, true))
+	{
+		Shell::Shutdown();
+		return -1;
+	}
+
+	// Rocket initialisation.
+	Rocket::Core::SetRenderInterface(&opengl_renderer);
+	shell_renderer->SetViewport(window_width, window_height);
+
+	ShellSystemInterface system_interface;
+	Rocket::Core::SetSystemInterface(&system_interface);
+
+	Rocket::Core::Initialise();
+
+	// Create the main Rocket context and set it on the shell's input layer.
+	context = Rocket::Core::CreateContext("main", Rocket::Core::Vector2i(window_width, window_height));
+	if (context == NULL)
+	{
+		Rocket::Core::Shutdown();
+		Shell::Shutdown();
+		return -1;
+	}
+
+	Rocket::Debugger::Initialise(context);
+	Input::SetContext(context);
+	shell_renderer->SetContext(context);
+
+    // Load bitmap font
+    Rocket::Core::FontDatabase::LoadFontFace("../../assets/Arial.fnt");
+	
+    // Load and show the demo document.
+	Rocket::Core::ElementDocument* document = context->LoadDocument("../../assets/bitmapfont.rml");
+	if (document != NULL)
+	{
+		document->Show();
+		document->RemoveReference();
+	}
+
+	Shell::EventLoop(GameLoop);
+
+	// Shutdown Rocket.
+	context->RemoveReference();
+	Rocket::Core::Shutdown();
+
+	Shell::CloseWindow();
+	Shell::Shutdown();
+
+	return 0;
+}

+ 147 - 0
Source/Core/BitmapFont/BitmapFontDefinitions.h

@@ -0,0 +1,147 @@
+/*
+ * 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 BITMAPFONTDEFINITIONS_H
+#define BITMAPFONTDEFINITIONS_H
+
+#include <Rocket/Core/Header.h>
+#include <Rocket/Core/Types.h>
+#include <Rocket/Core/Dictionary.h>
+#include <set>
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+	struct FontInfo
+	{
+		String FamilyName;
+		String Source;
+		String BitmapSource;
+		int Size;
+		Font::Style Style;
+		Font::Weight Weight;
+	};
+
+	struct CharacterCommonInfo
+	{
+		int LineHeight;
+		int BaseLine;
+		int ScaleWidth;
+		int ScaleHeight;
+		int CharacterCount;
+		int KerningCount;
+	};
+
+	struct CharacterInfo
+	{
+		int Id;
+		int X;
+		int Y;
+		int Width;
+		int Height;
+		int XOffset;
+		int YOffset;
+		int Advance;
+	};
+
+	struct KerningInfo
+	{
+		int FirstCharacterId;
+		int SecondCharacterId;
+		int KerningAmount;
+	};
+
+	class BitmapFontDefinitions
+	{
+	public:
+		FontInfo Face;
+		CharacterCommonInfo CommonCharactersInfo;
+		CharacterInfo *CharactersInfo;
+		KerningInfo *KerningsInfo;
+
+		int BM_Helper_GetCharacterTableIndex( int unicode_code )
+		{
+			return BinarySearch( unicode_code, 0, CommonCharactersInfo.CharacterCount );
+		}
+
+		int BM_Helper_GetXKerning( int left_uni_id, int right_uni_id )
+		{
+			for ( int i = 0; i < this->CommonCharactersInfo.KerningCount; i++ )
+			{
+				if ( this->KerningsInfo[i].FirstCharacterId == left_uni_id && this->KerningsInfo[i].SecondCharacterId == right_uni_id )
+				{
+					return this->KerningsInfo[i].KerningAmount;
+				}
+			}
+
+			return 0;
+		}
+
+	private:
+
+		int BinarySearch( int unicode_code, int min_index, int max_index )
+		{
+			if ( abs( max_index - min_index ) <= 1 )
+			{
+				if ( this->CharactersInfo[ min_index ].Id == unicode_code )
+				{
+					return min_index;
+				}
+				else if ( this->CharactersInfo[ max_index ].Id == unicode_code )
+				{
+					return max_index;
+				}
+				else
+				{
+					return -1;
+				}
+			}
+			else
+			{
+				int mid_index = ( min_index + max_index ) / 2;
+
+				if ( this->CharactersInfo[ mid_index ].Id == unicode_code )
+				{
+					return mid_index;
+				}
+				else if ( this->CharactersInfo[ mid_index ].Id > unicode_code )
+				{
+					return BinarySearch( unicode_code, min_index, mid_index );
+				}
+				else
+				{
+					return BinarySearch( unicode_code, mid_index, max_index );
+				}
+			}
+		}
+	};
+
+}
+}
+}
+#endif

+ 130 - 0
Source/Core/BitmapFont/FontFace.cpp

@@ -0,0 +1,130 @@
+/*
+ * 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 <Rocket/Core/Log.h>
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+FontFace::FontFace(BitmapFontDefinitions *_face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream)
+{
+	face = _face;
+}
+
+FontFace::~FontFace()
+{
+	ReleaseFace();
+}
+
+// Returns a handle for positioning and rendering this face at the given size.
+Rocket::Core::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 (FontFaceHandle*)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 (FontFaceHandle*)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 structure.
+void FontFace::ReleaseFace()
+{
+	delete face;
+}
+
+}
+}
+}

+ 68 - 0
Source/Core/BitmapFont/FontFace.h

@@ -0,0 +1,68 @@
+/*
+ * 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 ROCKETCOREBITMAPFONTFACE_H
+#define ROCKETCOREBITMAPFONTFACE_H
+
+#include "../../../Include/Rocket/Core/FontFace.h"
+#include "BitmapFontDefinitions.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+class FontFaceHandle;
+
+/**
+	@author Peter Curry
+ */
+
+class FontFace : public Rocket::Core::FontFace
+{
+public:
+	FontFace(BitmapFontDefinitions *_face, Font::Style style, Font::Weight weight, bool release_stream);
+	~FontFace();
+
+	/// 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.
+	Rocket::Core::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:
+	BitmapFontDefinitions *face;
+};
+
+}
+}
+}
+
+#endif

+ 428 - 0
Source/Core/BitmapFont/FontFaceHandle.cpp

@@ -0,0 +1,428 @@
+/*
+ * 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 "FontFaceLayer.h"
+#include <algorithm>
+#include "../TextureLayout.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+class FontEffectSort
+{
+public:
+	bool operator()(const Rocket::Core::FontEffect* lhs, const Rocket::Core::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;
+
+	base_layer = NULL;
+}
+
+FontFaceHandle::~FontFaceHandle()
+{
+}
+
+// Initialises the handle so it is able to render text.
+bool FontFaceHandle::Initialise(BitmapFontDefinitions *bm_face, const String& _charset, int _size)
+{
+	this->bm_face = bm_face;
+	size = _size;
+	line_height = _size;
+	texture_width = bm_face->CommonCharactersInfo.ScaleWidth;
+	texture_height = bm_face->CommonCharactersInfo.ScaleHeight;
+	raw_charset = _charset;
+
+	// Construct proper path to texture
+	URL fnt_source = bm_face->Face.Source;
+	URL bitmap_source = bm_face->Face.BitmapSource;
+	if(bitmap_source.GetPath().Empty())
+	{
+		texture_source = fnt_source.GetPath() + bitmap_source.GetFileName();
+		if(!bitmap_source.GetExtension().Empty())
+		{
+			texture_source += "." + bitmap_source.GetExtension();
+		}
+	}
+	else
+	{
+		texture_source = bitmap_source.GetPathedFileName();
+	}
+
+	if (!UnicodeRange::BuildList(charset, raw_charset))
+	{
+		Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString());
+		return false;
+	}
+
+	// Construct the list of the characters specified by the charset.
+	for (size_t i = 0; i < charset.size(); ++i)
+		BuildGlyphMap(bm_face, charset[i]);
+
+	// Generate the metrics for the handle.
+	GenerateMetrics(bm_face);
+
+	// 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 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, Rocket::Core::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)
+	{
+		Rocket::Core::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, line_vertices.size() - 4);
+}
+
+// Destroys the handle.
+void FontFaceHandle::OnReferenceDeactivate()
+{
+	delete this;
+}
+
+void FontFaceHandle::GenerateMetrics(BitmapFontDefinitions *bm_face)
+{
+	line_height = bm_face->CommonCharactersInfo.LineHeight;
+	baseline = bm_face->CommonCharactersInfo.BaseLine;
+
+	underline_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine;
+	baseline += int( underline_position / 1.6f );
+	underline_thickness = 1.0f;
+
+	average_advance = 0;
+	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+		average_advance += i->advance;
+
+	// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
+	average_advance = Math::RealToInteger((float) average_advance / (glyphs.size() * 0.9f));
+
+	// Determine the x-height of this font face.
+	word x = (word) 'x';
+	int index = bm_face->BM_Helper_GetCharacterTableIndex( x );// FT_Get_Char_Index(ft_face, x);
+
+	if ( index >= 0)
+		x_height = bm_face->CharactersInfo[ index ].Height;
+	else
+		x_height = 0;
+}
+
+void FontFaceHandle::BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range)
+{
+	glyphs.resize(unicode_range.max_codepoint + 1);
+
+	for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code)
+	{
+		int index = bm_face->BM_Helper_GetCharacterTableIndex( character_code );
+
+		if ( index < 0 )
+		{
+			continue;
+		}
+
+		FontGlyph glyph;
+		glyph.character = character_code;
+		BuildGlyph(glyph, &bm_face->CharactersInfo[ index ] );
+		glyphs[character_code] = glyph;
+	}
+}
+
+void Rocket::Core::BitmapFont::FontFaceHandle::BuildGlyph(FontGlyph& glyph, CharacterInfo *bm_glyph)
+{
+	// Set the glyph's dimensions.
+	glyph.dimensions.x = bm_glyph->Width;
+	glyph.dimensions.y = bm_glyph->Height;
+
+	// Set the glyph's bearing.
+	glyph.bearing.x = bm_glyph->XOffset;
+	glyph.bearing.y = bm_glyph->YOffset;
+
+	// Set the glyph's advance.
+	glyph.advance = bm_glyph->Advance;
+
+	// Set the glyph's bitmap position.
+	glyph.bitmap_dimensions.x = bm_glyph->X;
+	glyph.bitmap_dimensions.y = bm_glyph->Y;
+
+	glyph.bitmap_data = NULL;
+}
+
+int Rocket::Core::BitmapFont::FontFaceHandle::GetKerning(word lhs, word rhs) const
+{
+	if( bm_face != NULL)
+	{
+		return bm_face->BM_Helper_GetXKerning(lhs, rhs);
+	}
+
+	return 0;
+}
+
+// Generates (or shares) a layer derived from a font effect.
+Rocket::Core::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;
+
+	Rocket::Core::FontFaceLayer* layer = new Rocket::Core::BitmapFont::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.
+		Rocket::Core::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] = (Rocket::Core::FontFaceLayer*) layer;
+	}
+
+	return (Rocket::Core::FontFaceLayer*)layer;
+}
+
+}
+}
+}

+ 136 - 0
Source/Core/BitmapFont/FontFaceHandle.h

@@ -0,0 +1,136 @@
+/*
+ * 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 ROCKETCOREBITMAPFONTFONTFACEHANDLE_H
+#define ROCKETCOREBITMAPFONTFONTFACEHANDLE_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 "../FontFaceHandle.h"
+#include "BitmapFontDefinitions.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+/**
+	@author Peter Curry
+ */
+
+class FontFaceHandle : public Rocket::Core::FontFaceHandle
+{
+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(BitmapFontDefinitions *bm_face, const String& charset, int size);
+
+	/// 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(Rocket::Core::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;
+
+	const String & GetTextureSource() const
+	{
+		return texture_source;
+	}
+
+	unsigned int GetTextureWidth() const
+	{
+		return texture_width;
+	}
+
+	unsigned int GetTextureHeight() const
+	{
+		return texture_height;
+	}
+
+protected:
+	/// Destroys the handle.
+	virtual void OnReferenceDeactivate();
+
+private:
+	void GenerateMetrics(BitmapFontDefinitions *bm_face);
+
+	void BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range);
+	void BuildGlyph(FontGlyph& glyph, CharacterInfo *ft_glyph);
+	int GetKerning(word lhs, word rhs) const;
+
+	// Generates (or shares) a layer derived from a font effect.
+	virtual FontFaceLayer* GenerateLayer(FontEffect* font_effect);
+
+	BitmapFontDefinitions * bm_face;
+	String texture_source;
+	String texture_directory;
+	unsigned int texture_width;
+	unsigned int texture_height;
+};
+
+}
+}
+}
+
+#endif

+ 127 - 0
Source/Core/BitmapFont/FontFaceLayer.cpp

@@ -0,0 +1,127 @@
+/*
+ * 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 "FontFaceHandle.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+FontFaceLayer::FontFaceLayer() : Rocket::Core::FontFaceLayer()
+{
+	handle = NULL;
+	effect = NULL;
+}
+
+FontFaceLayer::~FontFaceLayer()
+{
+}
+
+// Generates the character and texture data for the layer.
+bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, FontEffect* _effect, const Rocket::Core::FontFaceLayer* clone, bool deep_clone)
+{
+	(void)(_effect);
+
+	Rocket::Core::BitmapFont::FontFaceHandle
+		* bm_font_face_handle;
+
+	handle = _handle;
+
+	bm_font_face_handle = ( Rocket::Core::BitmapFont::FontFaceHandle * ) handle;
+
+	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]);
+	}
+	else
+	{
+		// Load texture from file
+		Texture texture;
+		if (!texture.Load( bm_font_face_handle->GetTextureSource() ))
+			return false;
+
+		textures.push_back(texture);
+
+		// 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;
+
+			if(glyph.dimensions.x <= 0 || glyph.dimensions.y <= 0)
+				continue;
+
+			Vector2i glyph_origin( glyph.bitmap_dimensions.x, glyph.bitmap_dimensions.y ); // position in texture
+			Vector2i glyph_dimensions = glyph.dimensions; // size of char
+
+			Character character;
+			character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y) - handle->GetBaseline()*3 );
+			character.dimensions = Vector2f((float) glyph.dimensions.x, (float) glyph.dimensions.y);
+
+			// Set the character's texture index.
+			character.texture_index = 0;
+
+			// Generate the character's texture coordinates.
+			character.texcoords[0].x = float(glyph_origin.x) / float(bm_font_face_handle->GetTextureWidth());
+			character.texcoords[0].y = float(glyph_origin.y) / float(bm_font_face_handle->GetTextureHeight());
+			character.texcoords[1].x = float(glyph_origin.x + character.dimensions.x) / float(bm_font_face_handle->GetTextureWidth());
+			character.texcoords[1].y = float(glyph_origin.y + character.dimensions.y) / float(bm_font_face_handle->GetTextureHeight());
+
+			characters[glyph.character] = character;
+
+			// Add the character's dimensions into the texture layout engine.
+			texture_layout.AddRectangle(glyph.character, glyph_dimensions);
+		}
+
+		// 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;
+
+	}
+	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)
+{
+	return true;
+}
+
+}
+}
+}

+ 78 - 0
Source/Core/BitmapFont/FontFaceLayer.h

@@ -0,0 +1,78 @@
+/*
+ * 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 ROCKETCOREBITMAPFONTFACELAYER_H
+#define ROCKETCOREBITMAPFONTFACELAYER_H
+
+#include <Rocket/Core/Header.h>
+#include <Rocket/Core/FontGlyph.h>
+#include <Rocket/Core/Geometry.h>
+#include <Rocket/Core/GeometryUtilities.h>
+#include <Rocket/Core/String.h>
+#include "../FontFaceLayer.h"
+
+namespace Rocket {
+namespace Core {
+
+	class TextureLayout;
+
+namespace BitmapFont {
+
+/**
+	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 Rocket::Core::FontFaceLayer
+{
+public:
+	FontFaceLayer();
+	virtual ~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.
+	virtual bool Initialise(const FontFaceHandle* handle, FontEffect* effect = NULL, const Rocket::Core::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.
+	virtual bool GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id);
+
+};
+
+}
+}
+}
+
+#endif

+ 55 - 0
Source/Core/BitmapFont/FontFamily.cpp

@@ -0,0 +1,55 @@
+/*
+ * 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 {
+namespace BitmapFont {
+
+FontFamily::FontFamily(const String& name) : Rocket::Core::FontFamily(name)
+{
+}
+
+FontFamily::~FontFamily()
+{
+}
+
+// Adds a new face to the family.
+bool FontFamily::AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream)
+{
+	Rocket::Core::FontFace* face = new FontFace((BitmapFontDefinitions*)bm_face, style, weight, release_stream);
+	font_faces.push_back(face);
+
+	return true;
+}
+
+}
+}
+}

+ 66 - 0
Source/Core/BitmapFont/FontFamily.h

@@ -0,0 +1,66 @@
+/*
+ * 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 ROCKETCOREBITMAPFONTFAMILY_H
+#define ROCKETCOREBITMAPFONTFAMILY_H
+
+#include "../../../Include/Rocket/Core/Font.h"
+#include "../../../Include/Rocket/Core/FontFamily.h"
+#include "BitmapFontDefinitions.h"
+
+namespace Rocket {
+namespace Core {
+
+class FontFace;
+class FontFaceHandle;
+
+namespace BitmapFont {
+
+/**
+	@author Peter Curry
+ */
+
+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( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream);
+};
+
+}
+}
+}
+
+#endif

+ 112 - 0
Source/Core/BitmapFont/FontParser.cpp

@@ -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.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontParser.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+FontParser::FontParser( BitmapFontDefinitions *face )
+	: BaseXMLParser()
+{
+	bm_face = face;
+	char_id = 0;
+	kern_id = 0;
+}
+
+FontParser::~FontParser()
+{
+}
+
+// Called when the parser finds the beginning of an element tag.
+void FontParser::HandleElementStart(const String& name, const XMLAttributes& attributes)
+{
+	if ( name == "info" )
+	{
+		bm_face->Face.FamilyName = attributes.Get( "face" )->Get< String >();
+		bm_face->Face.Size = attributes.Get( "size" )->Get< int >();
+		bm_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+		bm_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
+		bm_face->Face.BitmapSource = attributes.Get( "src" )->Get< String >();
+	}
+	else if ( name == "common" )
+	{
+		bm_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >();
+		bm_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >() * -1;
+		bm_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >();
+		bm_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >();
+		bm_face->CommonCharactersInfo.CharacterCount = 0;
+		bm_face->CommonCharactersInfo.KerningCount = 0;
+	}
+	else if ( name == "chars" )
+	{
+		bm_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >();
+		bm_face->CharactersInfo = new CharacterInfo[ attributes.Get( "count" )->Get< int >() ];
+	}
+	else if ( name == "char" )
+	{
+		bm_face->CharactersInfo[ char_id ].Id = attributes.Get( "id" )->Get< int >();
+		bm_face->CharactersInfo[ char_id ].X = attributes.Get( "x" )->Get< int >(); //The left position of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].Y = attributes.Get( "y" )->Get< int >(); //The top position of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].Width = attributes.Get( "width" )->Get< int >(); //The width of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].Height = attributes.Get( "height" )->Get< int >(); //The height of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >();
+		bm_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >();
+		bm_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >();
+
+		char_id++;
+	}
+	else if ( name == "kernings" )
+	{
+		bm_face->CommonCharactersInfo.KerningCount = attributes.Get( "count" )->Get< int >();
+		bm_face->KerningsInfo = new KerningInfo[ attributes.Get( "count" )->Get< int >() ];
+	}
+	else if ( name == "kerning" )
+	{
+		bm_face->KerningsInfo[ kern_id ].FirstCharacterId = attributes.Get( "first" )->Get< int >();
+		bm_face->KerningsInfo[ kern_id ].SecondCharacterId = attributes.Get( "second" )->Get< int >();
+		bm_face->KerningsInfo[ kern_id ].KerningAmount = attributes.Get( "amount" )->Get< int >();
+
+		kern_id++;
+	}
+}
+
+// Called when the parser finds the end of an element tag.
+void FontParser::HandleElementEnd(const String& ROCKET_UNUSED(name))
+{
+}
+
+// Called when the parser encounters data.
+void FontParser::HandleData(const String& ROCKET_UNUSED(data))
+{
+}
+
+}
+}
+}

+ 68 - 0
Source/Core/BitmapFont/FontParser.h

@@ -0,0 +1,68 @@
+/*
+ * 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 BITMAPFONTPARSER_H
+#define BITMAPFONTPARSER_H
+
+#include <Rocket/Core/Header.h>
+#include <Rocket/Core/Types.h>
+#include <Rocket/Core/Dictionary.h>
+#include "BitmapFontDefinitions.h"
+#include <set>
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+/**
+	@author Peter Curry
+ */
+
+class FontParser : public BaseXMLParser
+{
+	public:
+		FontParser( BitmapFontDefinitions *face );
+		virtual ~FontParser();
+
+		/// Called when the parser finds the beginning of an element tag.
+		virtual void HandleElementStart(const String& name, const XMLAttributes& attributes);
+		/// Called when the parser finds the end of an element tag.
+		virtual void HandleElementEnd(const String& name);
+		/// Called when the parser encounters data.
+		virtual void HandleData(const String& data);
+
+	private:
+		FontParser();
+		BitmapFontDefinitions *bm_face;
+		int char_id;
+		int kern_id;
+};
+
+}
+}
+}
+#endif

+ 208 - 0
Source/Core/BitmapFont/FontProvider.cpp

@@ -0,0 +1,208 @@
+/*
+ * 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/BitmapFont/FontProvider.h>
+#include "../FontFaceHandle.h"
+#include <Rocket/Core/FontDatabase.h>
+#include <Rocket/Core/StreamMemory.h>
+#include "FontFamily.h"
+#include <Rocket/Core.h>
+#include "BitmapFontDefinitions.h"
+#include "FontParser.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+
+FontProvider* FontProvider::instance = 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();
+
+		FontDatabase::AddFontProvider(instance);
+	}
+
+	return true;
+}
+
+void FontProvider::Shutdown()
+{
+	if (instance != NULL)
+	{
+		FontDatabase::RemoveFontProvider(instance);
+		delete instance;
+		instance = NULL;
+	}
+}
+
+// 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)
+{
+	BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name);
+
+	if (bm_font == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+		return false;
+	}
+
+	Font::Style style = bm_font->Face.Style;
+	Font::Weight weight = bm_font->Face.Weight;
+
+	if (instance->AddFace(bm_font, bm_font->Face.FamilyName, style, weight, true))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return false;
+	}
+
+	return true;
+}
+
+// Loads a new font face.
+bool FontProvider::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight)
+{
+	BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name);
+	if (bm_font == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+		return false;
+	}
+
+	if (instance->AddFace(bm_font, family, style, weight, true))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return false;
+	}
+
+	return true;
+}
+
+bool FontProvider::LoadFontFace(const byte* data, int data_length)
+{
+	// TODO: Loading from memory
+	return false;
+}
+
+// Adds a new font face to the database, loading from memory.
+bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
+{
+	// TODO Loading from memory
+	return false;
+}
+
+// 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((BitmapFontDefinitions *) face, style, weight, release_stream);
+	return true;
+}
+
+// Loads a FreeType face.
+void* FontProvider::LoadFace(const String& file_name)
+{
+	BitmapFontDefinitions *bm_face = new BitmapFontDefinitions();
+	FontParser parser( bm_face );
+
+	FileInterface* file_interface = GetFileInterface();
+	FileHandle handle = file_interface->Open(file_name);
+
+	if (!handle)
+	{
+		return NULL;
+	}
+
+	size_t length = file_interface->Length(handle);
+
+	byte* buffer = new byte[length];
+	file_interface->Read(buffer, length, handle);
+	file_interface->Close(handle);
+
+	StreamMemory* stream = new StreamMemory( buffer, length );
+	stream->SetSourceURL( file_name );
+
+	parser.Parse( stream );
+
+	bm_face->Face.Source = file_name;
+	return bm_face;
+}
+
+// Loads a FreeType face from memory.
+void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data)
+{
+	URL file_url = source + ".fnt";
+
+	BitmapFontDefinitions *bm_face = new BitmapFontDefinitions();
+	FontParser parser( bm_face );
+	StreamMemory* stream = new StreamMemory( data, data_length );
+	stream->SetSourceURL( file_url );
+
+	parser.Parse( stream );
+
+	bm_face->Face.Source = file_url.GetPathedFileName();
+	return bm_face;
+}
+
+}
+}
+}

+ 94 - 158
Source/Core/FontDatabase.cpp

@@ -26,22 +26,21 @@
  */
 
 #include "precompiled.h"
-#include "../../Include/Rocket/Core/FontDatabase.h"
-#include "FontFamily.h"
-#include "../../Include/Rocket/Core.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include <Rocket/Core/FontDatabase.h>
+#include <Rocket/Core/FontFamily.h>
+#include <Rocket/Core.h>
+#include <Rocket/Core/FreeType/FontProvider.h>
+#include <Rocket/Core/BitmapFont/FontProvider.h>
 
 namespace Rocket {
 namespace Core {
 
 FontDatabase* FontDatabase::instance = NULL;
+FontDatabase::FontProviderTable FontDatabase::font_provider_table;
 
 typedef std::map< String, FontEffect* > FontEffectCache;
 FontEffectCache font_effect_cache;
 
-static FT_Library ft_library = NULL;
-
 FontDatabase::FontDatabase()
 {
 	ROCKET_ASSERT(instance == NULL);
@@ -60,13 +59,11 @@ 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;
+
+        if(!BitmapFont::FontProvider::Initialise())
+            return false;
 	}
 
 	return true;
@@ -76,14 +73,8 @@ 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();
+        BitmapFont::FontProvider::Shutdown();
 
 		delete instance;
 	}
@@ -92,105 +83,101 @@ 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;
-	}
+    FontProviderType font_provider_type = GetFontProviderType(file_name);
 
-	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;
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(file_name);
 
-	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;
-	}
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(file_name);
+
+        default:
+            return false;
+    }
 }
 
 // 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;
-	}
+    FontProviderType font_provider_type = GetFontProviderType(file_name);
 
-	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;
-	}
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(file_name, family, style, weight);
+
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(file_name, family, style, weight);
+
+        default:
+            return false;
+    }
 }
 
 // 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;
-	}
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(data, data_length);
 
-	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;
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(data, data_length);
 
-	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;
-	}
+        default:
+            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 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;
-	}
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(data, data_length, family, style, weight);
 
-	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;
-	}
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(data, data_length, family, style, weight);
+
+        default:
+            return false;
+    }
+}
+
+FontDatabase::FontProviderType FontDatabase::GetFontProviderType(const String& file_name)
+{
+    if(file_name.Find(".fnt") != String::npos)
+    {
+        return BitmapFont;
+    }
+    else
+    {
+        return FreeType;
+    }
 }
 
 // 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;
+
+    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 (*iterator).second->GetFaceHandle(charset, style, weight, size);
+    return NULL;
 }
 
 // Returns a font effect, either a newly-instanced effect from the factory or an identical shared
@@ -255,72 +242,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;
+        }
+    }
 }
 
 }

+ 2 - 95
Source/Core/FontFace.cpp

@@ -26,16 +26,15 @@
  */
 
 #include "precompiled.h"
-#include "FontFace.h"
+#include "../../Include/Rocket/Core/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)
+FontFace::FontFace(Font::Style _style, Font::Weight _weight, bool _release_stream)
 {
-	face = _face;
 	style = _style;
 	weight = _weight;
 
@@ -50,8 +49,6 @@ FontFace::~FontFace()
 		for (size_t i = 0; i < handle_list.size(); ++i)
 			handle_list[i]->RemoveReference();
 	}
-
-	ReleaseFace();
 }
 
 // Returns the style of the font face.
@@ -66,95 +63,5 @@ 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;
-	}
-}
-
 }
 }

+ 0 - 209
Source/Core/FontFaceHandle.cpp

@@ -55,8 +55,6 @@ FontFaceHandle::FontFaceHandle()
 	underline_position = 0;
 	underline_thickness = 0;
 
-	ft_face = NULL;
-
 	base_layer = NULL;
 }
 
@@ -69,50 +67,6 @@ FontFaceHandle::~FontFaceHandle()
 		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
 {
@@ -353,169 +307,6 @@ 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)
 {

+ 7 - 26
Source/Core/FontFaceHandle.h

@@ -36,8 +36,6 @@
 #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 {
@@ -54,13 +52,6 @@ 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;
@@ -87,18 +78,18 @@ public:
 	/// @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;
+	virtual int GetStringWidth(const WString& string, word prior_character = 0) const = 0;
 
 	/// 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);
+	virtual int GenerateLayerConfiguration(FontEffectMap& font_effects) = 0;
 	/// 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);
+	virtual bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id) = 0;
 
 	/// Generates the geometry required to render a single line of text.
 	/// @param[out] geometry An array of geometries to generate the geometry into.
@@ -106,14 +97,14 @@ public:
 	/// @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;
+	virtual int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const = 0;
 	/// 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;
+	virtual void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const = 0;
 
 	/// Returns the font face's raw charset (the charset range as a string).
 	/// @return The font face's charset.
@@ -125,24 +116,14 @@ public:
 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);
+	virtual int GetKerning(word lhs, word rhs) const = 0;
 
 	typedef std::vector< int > GlyphKerningList;
 	typedef std::vector< GlyphKerningList > FontKerningList;
 
-	FT_Face ft_face;
-
 	FontGlyphList glyphs;
+	FontKerningList kerning;
 
 	typedef std::map< const FontEffect*, FontFaceLayer* > FontLayerMap;
 	typedef std::map< String, FontFaceLayer* > FontLayerCache;

+ 3 - 3
Source/Core/FontFaceLayer.h

@@ -60,14 +60,14 @@ public:
 	/// @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);
+	virtual 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);
+	virtual 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.
@@ -107,7 +107,7 @@ public:
 	/// @return The layer's colour.
 	const Colourb& GetColour() const;
 
-private:
+// protected:
 	struct Character
 	{
 		Character() : texture_index(-1) { }

+ 2 - 11
Source/Core/FontFamily.cpp

@@ -26,8 +26,8 @@
  */
 
 #include "precompiled.h"
-#include "FontFamily.h"
-#include "FontFace.h"
+#include "../../Include/Rocket/Core/FontFamily.h"
+#include "../../Include/Rocket/Core/FontFace.h"
 
 namespace Rocket {
 namespace Core {
@@ -42,15 +42,6 @@ FontFamily::~FontFamily()
 		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)
 {

+ 45 - 0
Source/Core/FontProvider.cpp

@@ -0,0 +1,45 @@
+/*
+ * 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 {
+
+// 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 = font_families.find(family);
+	if (iterator == font_families.end())
+		return NULL;
+
+	return (*iterator).second->GetFaceHandle(charset, style, weight, size);
+}
+
+}
+}

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

@@ -0,0 +1,139 @@
+/*
+ * 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 {
+namespace FreeType {
+
+FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream)
+{
+	face = _face;
+}
+
+FontFace::~FontFace()
+{
+	ReleaseFace();
+}
+
+// Returns a handle for positioning and rendering this face at the given size.
+Rocket::Core::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 (Rocket::Core::FreeType::FontFaceHandle*)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 (Rocket::Core::FreeType::FontFaceHandle*)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;
+	}
+}
+
+}
+}
+}

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

@@ -0,0 +1,68 @@
+/*
+ * 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 ROCKETCOREFREETYPEFONTFACE_H
+#define ROCKETCOREFREETYPEFONTFACE_H
+
+#include "../../../Include/Rocket/Core/FontFace.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Rocket {
+namespace Core {
+namespace FreeType {
+/**
+	@author Peter Curry
+ */
+
+class FontFaceHandle;
+
+class FontFace : public Rocket::Core::FontFace
+{
+public:
+	FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream);
+	~FontFace();
+
+	/// 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.
+	Rocket::Core::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;
+};
+
+}
+}
+}
+
+#endif

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

@@ -0,0 +1,458 @@
+/*
+ * 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 {
+namespace FreeType {
+
+class FontEffectSort
+{
+public:
+	bool operator()(const FontEffect* lhs, const FontEffect* rhs)
+	{
+		return lhs->GetZIndex() < rhs->GetZIndex();
+	}
+};
+
+FontFaceHandle::FontFaceHandle()
+{
+	ft_face = NULL;
+}
+
+FontFaceHandle::~FontFaceHandle()
+{
+}
+
+// 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 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);
+}
+
+// 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;
+}
+
+}
+}
+}

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

@@ -0,0 +1,117 @@
+/*
+ * 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 ROCKETCOREFREETYPEFONTFACEHANDLE_H
+#define ROCKETCOREFREETYPEFONTFACEHANDLE_H
+
+#include "../../../Include/Rocket/Core/ReferenceCountable.h"
+#include "../UnicodeRange.h"
+#include "../FontFaceHandle.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;
+
+namespace FreeType {
+
+/**
+	@author Peter Curry
+ */
+
+class FontFaceHandle : public Rocket::Core::FontFaceHandle
+{
+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 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;
+
+protected:
+	/// Destroys the handle.
+	virtual void OnReferenceDeactivate();
+
+	int GetKerning(word lhs, word rhs) const;
+
+private:
+	void GenerateMetrics(void);
+
+	void BuildGlyphMap(const UnicodeRange& unicode_range);
+	void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph);
+
+	FT_Face ft_face;
+};
+
+}
+}
+}
+
+#endif

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

@@ -0,0 +1,58 @@
+/*
+ * 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 {
+namespace FreeType
+{
+
+FontFamily::FontFamily(const String& name) : Rocket::Core::FontFamily(name)
+{
+
+}
+
+FontFamily::~FontFamily()
+{
+
+}
+
+// Adds a new face to the family.
+bool FontFamily::AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream)
+{
+	FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream);
+	font_faces.push_back(face);
+
+	return true;
+}
+
+}
+}
+}

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

@@ -0,0 +1,67 @@
+/*
+ * 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(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream);
+};
+
+}
+}
+}
+
+#endif

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

@@ -0,0 +1,258 @@
+/*
+ * 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();
+
+		FontDatabase::AddFontProvider(instance);
+
+		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;
+	}
+}
+
+// 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)
+{
+	FontFamily* font_family = NULL;
+	FontFamilyMap::iterator iterator = font_families.find(family);
+	if (iterator != font_families.end())
+		font_family = (FontFamily*)(*iterator).second;
+	else
+	{
+		font_family = new FontFamily(family);
+		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;
+}
+
+}
+}
+}

+ 4 - 1
Source/Core/TextureLayoutTexture.cpp

@@ -65,7 +65,10 @@ int TextureLayoutTexture::Generate(TextureLayout& layout, int maximum_dimensions
 
 		if (!rectangle.IsPlaced())
 		{
-			square_pixels += (rectangle.GetDimensions().x + 1) * (rectangle.GetDimensions().y + 1);
+			int x = rectangle.GetDimensions().x + 1;
+			int y = rectangle.GetDimensions().y + 1;
+
+			square_pixels += x*y;
 			++unplaced_rectangles;
 		}
 	}

+ 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()