Browse Source

A lot of changes

Patryk Konopka 10 years ago
parent
commit
870ff44c9b

+ 13 - 2
Build/cmake/FileList.cmake

@@ -40,8 +40,13 @@ set(Core_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.h
-    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceLayer.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/BM_Font.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
@@ -135,6 +140,7 @@ set(Core_PUB_HDR_FILES
     ${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
@@ -242,9 +248,14 @@ set(Core_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/FontProvider.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.cpp
-    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceLayer.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontProvider.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/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

+ 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

+ 3 - 1
Include/Rocket/Core/FontDatabase.h

@@ -54,7 +54,7 @@ public:
     enum FontProviderType
     {
         FreeType = 0,
-        Bitmap
+        BitmapFont
     };
 
 	static bool Initialise();
@@ -115,6 +115,8 @@ private:
 	FontDatabase(void);
 	~FontDatabase(void);
 
+    static FontProviderType GetFontProviderType(const String& file_name);
+
     typedef std::vector< FontProvider *> FontProviderTable;
 
     static FontProviderTable font_provider_table;

+ 1 - 2
Include/Rocket/Core/FontFamily.h

@@ -28,9 +28,8 @@
 #ifndef ROCKETCOREFONTFAMILY_H
 #define ROCKETCOREFONTFAMILY_H
 
+#include <Rocket/Core/StringUtilities.h>
 #include "Font.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
 
 namespace Rocket {
 namespace Core {

+ 3 - 3
Include/Rocket/Core/FreeType/FontProvider.h

@@ -28,9 +28,9 @@
 #ifndef ROCKETCOREFREETYPEFONTPROVIDER_H
 #define ROCKETCOREFREETYPEFONTPROVIDER_H
 
-#include <Rocket/Core/StringUtilities.h>
-#include <Rocket/Core/Font.h>
-#include <Rocket/Core/FontProvider.h>
+#include "../StringUtilities.h"
+#include "../Font.h"
+#include "../FontProvider.h"
 
 namespace Rocket {
 namespace Core {

+ 273 - 0
Samples/assets/Arial.fnt

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


+ 184 - 0
Source/Core/BitmapFont/BM_Font.h

@@ -0,0 +1,184 @@
+/*
+ * 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 Padding
+    {
+        int Up,
+            Right,
+            Down,
+            Left;
+    };
+
+    struct Spacing
+    {
+        int Horizontal,
+            Vertical;
+    };
+
+    struct FontInfo
+    {
+        String FamilyName;
+        String Source;
+        String Directory;
+        int Size;
+        Font::Style Style;
+        Font::Weight Weight;
+        String CharsetName;
+        bool IsUnicode;
+        int StretchHeight;
+        bool IsSmoothed;
+        int SuperSamplingLevel;
+        Padding FontPadding;
+        Spacing FontSpacing;
+        int Outline;
+    };
+
+    struct CharacterCommonInfo
+    {
+        int LineHeight;
+        int BaseLine;
+        int ScaleWidth;
+        int ScaleHeight;
+        int PageCount;
+        bool IsPacked;
+        int AlphaChanelUsage;
+        int RedChanelUsage;
+        int GreenChanelUsage;
+        int BlueChanelUsage;
+        int CharacterCount;
+        int KerningCount;
+    };
+
+    struct PageInfo
+    {
+        int Id;
+        String FileName;
+    };
+
+    struct CharacterInfo
+    {
+        int Id;
+        int X;
+        int Y;
+        int Width;
+        int Height;
+        int XOffset;
+        int YOffset;
+        int Advance;
+        int PageId;
+        int ChannelUsed;
+    };
+
+    struct KerningInfo
+    {
+        int FirstCharacterId;
+        int SecondCharacterId;
+        int KerningAmount;
+    };
+
+    class BM_Font
+    {
+    public:
+        FontInfo Face;
+        CharacterCommonInfo CommonCharactersInfo;
+        PageInfo *PagesInfo;
+        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

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

@@ -0,0 +1,131 @@
+/*
+ * 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(BM_Font *_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;
+    return 0;
+}
+
+// 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 "BM_Font.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+class FontFaceHandle;
+
+/**
+    @author Peter Curry
+ */
+
+class FontFace : public Rocket::Core::FontFace
+{
+public:
+    FontFace(BM_Font *_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:
+    BM_Font *face;
+};
+
+}
+}
+}
+
+#endif

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

@@ -0,0 +1,450 @@
+/*
+ * 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(BM_Font *bm_face, const String& _charset, int _size)
+{
+    ROCKET_ASSERT( bm_face->CommonCharactersInfo.ScaleHeight == bm_face->CommonCharactersInfo.ScaleWidth );
+
+    size = _size;
+    TextureBaseName = bm_face->Face.Source;
+    TextureDirectory = bm_face->Face.Directory;
+    TextureSize = bm_face->CommonCharactersInfo.ScaleHeight;
+    raw_charset = _charset;
+
+    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(BM_Font *bm_face)
+{
+    line_height = bm_face->CommonCharactersInfo.LineHeight;
+    baseline = bm_face->CommonCharactersInfo.BaseLine;
+
+    underline_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine;//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);
+*/
+    baseline += int( underline_position / 1.5f );
+    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(BM_Font *bm_face, 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 = 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;
+
+    if ( bm_glyph->PageId > 0 )
+    {
+        Log::Message( Log::LT_WARNING, "Multiple page not supported" );
+    }
+
+    // Set the glyph's bitmap position.
+    glyph.bitmap_dimensions.x = bm_glyph->X;
+    glyph.bitmap_dimensions.y = bm_glyph->Y;
+
+    glyph.bitmap_data = NULL;
+}
+
+void Rocket::Core::BitmapFont::FontFaceHandle::BuildKerning(BM_Font *bm_face)
+{
+    // Compile the kerning information for this character if the font includes it.
+//    if ( bm_face->CommonCharactersInfo.KerningCount > 0 )
+//    {
+//        for (size_t i = 0; i < charset.size(); ++i)
+//        {
+//            for (word rhs = (word) (Math::Max< unsigned int >(charset[i].min_codepoint, 32)); rhs <= charset[i].max_codepoint; ++rhs)
+//            {
+//                GlyphKerningMap& glyph_kerning = kerning.insert(FontKerningMap::value_type(rhs, GlyphKerningMap())).first->second;
+
+//                for (size_t j = 0; j < charset.size(); ++j)
+//                {
+//                    for (word lhs = (word) (Math::Max< unsigned int >(charset[j].min_codepoint, 32)); lhs <= charset[j].max_codepoint; ++lhs)
+//                    {
+//                        int kerning = bm_face->BM_Helper_GetXKerning( lhs, rhs );
+//                        if (kerning != 0)
+//                            glyph_kerning[lhs] = kerning;
+//                    }
+//                }
+//            }
+//        }
+//    }
+}
+
+int Rocket::Core::BitmapFont::FontFaceHandle::GetKerning(word lhs, word rhs) const
+{
+//    FontKerningMap::const_iterator rhs_iterator = kerning.find(rhs);
+//    if (rhs_iterator == kerning.end())
+//        return 0;
+
+//    GlyphKerningMap::const_iterator lhs_iterator = rhs_iterator->second.find(lhs);
+//    if (lhs_iterator == rhs_iterator->second.end())
+//        return 0;
+
+//    return lhs_iterator->second;
+    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;
+}
+
+}
+}
+}

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

@@ -0,0 +1,137 @@
+/*
+ * 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 "BM_Font.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(BM_Font *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(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 & GetTextureBaseName() const
+    {
+        return TextureBaseName;
+    }
+
+    const String & GetTextureDirectory() const
+    {
+        return TextureDirectory;
+    }
+
+    int GetTextureSize() const
+    {
+        return TextureSize;
+    }
+
+
+protected:
+    /// Destroys the handle.
+    virtual void OnReferenceDeactivate();
+
+private:
+    void GenerateMetrics(BM_Font *bm_face);
+
+    void BuildGlyphMap(BM_Font *bm_face, const UnicodeRange& unicode_range);
+    void BuildGlyph(FontGlyph& glyph, CharacterInfo *ft_glyph);
+
+    void BuildKerning(BM_Font *bm_face);
+    int GetKerning(word lhs, word rhs) const;
+
+    // Generates (or shares) a layer derived from a font effect.
+    virtual FontFaceLayer* GenerateLayer(FontEffect* font_effect);
+
+    String TextureBaseName;
+    String TextureDirectory;
+    int TextureSize;
+};
+
+}
+}
+}
+
+#endif

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

@@ -0,0 +1,122 @@
+/*
+ * 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()
+{
+    if (effect != NULL)
+        effect->RemoveReference();
+}
+
+// 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)
+{
+    Rocket::Core::BitmapFont::FontFaceHandle
+        * bm_font_face_handle;
+
+    handle = _handle;
+    //effect = _effect;
+
+    bm_font_face_handle = ( Rocket::Core::BitmapFont::FontFaceHandle * ) handle;
+
+    if (effect != NULL)
+    {
+        //effect->AddReference();
+        //Log::Message( Log::LT_WARNING, "Effects are not supported" );
+    }
+
+    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
+    {
+        // Initialise the texture layout for the glyphs.
+        for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+        {
+            const FontGlyph& glyph = *i;
+
+            Vector2i glyph_origin( glyph.bitmap_dimensions.x, glyph.bitmap_dimensions.y ); // position in texture
+            Vector2i glyph_dimension = glyph.dimensions; // size of char
+
+            Character character;
+            character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y));
+            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->GetTextureSize());
+            character.texcoords[0].y = float(glyph_origin.y) / float(bm_font_face_handle->GetTextureSize());
+            character.texcoords[1].x = float(glyph_origin.x + character.dimensions.x) / float(bm_font_face_handle->GetTextureSize());
+            character.texcoords[1].y = float(glyph_origin.y + character.dimensions.y) / float(bm_font_face_handle->GetTextureSize());
+
+            characters[glyph.character] = character;
+
+        }
+
+        Texture texture;
+        if (!texture.Load( bm_font_face_handle->GetTextureBaseName() + "_0.tga", bm_font_face_handle->GetTextureDirectory() ) )
+            return false;
+        textures.push_back(texture);
+    }
+
+
+    return true;
+}
+
+// Generates the texture data for a layer (for the texture database).
+bool FontFaceLayer::GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id)
+{
+    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( BM_Font *bm_face, Font::Style style, Font::Weight weight, bool release_stream)
+{
+    Rocket::Core::FontFace* face = new FontFace(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 "BM_Font.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( BM_Font *bm_face, Font::Style style, Font::Weight weight, bool release_stream);
+};
+
+}
+}
+}
+
+#endif

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


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


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

@@ -0,0 +1,247 @@
+/*
+ * 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 "BM_Font.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)
+{
+//    BM_Font *bm_font = (BM_Font*) 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)
+{
+//    BM_Font *bm_font = (BM_Font*) 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,  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;
+}
+
+bool FontProvider::LoadFontFace(const byte* data, int data_length)
+{
+    //    BM_Font *bm_font = (BM_Font*) instance->LoadFace(data, data_length, family, false);
+    //    if (bm_font == NULL)
+    //    {
+    //        Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
+    //        return false;
+    //    }
+
+    //    if (instance->AddFace(bm_font, bm_font->Face.FamilyName, style, weight, false))
+    //    {
+    //        Log::Message(Log::LT_INFO, "Loaded font face %s (from byte stream).", bm_font->Face.FamilyName.CString());
+    //        return true;
+    //    }
+    //    else
+    //    {
+    //        Log::Message(Log::LT_ERROR, "Failed to load font face %s (from byte stream).", bm_font->Face.FamilyName.CString());
+    //        return false;
+    //    }
+    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)
+{
+//    BM_Font *bm_font = (BM_Font*) instance->LoadFace(data, data_length, family, false);
+//    if (bm_font == NULL)
+//    {
+//        Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
+//        return false;
+//    }
+
+//    if (instance->AddFace(bm_font, family, style, weight, false))
+//    {
+//        Log::Message(Log::LT_INFO, "Loaded font face %s (from byte stream).", bm_font->Face.FamilyName.CString());
+//        return true;
+//    }
+//    else
+//    {
+//        Log::Message(Log::LT_ERROR, "Failed to load font face %s (from byte stream).", bm_font->Face.FamilyName.CString());
+//        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 = 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((BM_Font *) face, style, weight, release_stream);
+    return true;
+}
+
+// Loads a FreeType face.
+void* FontProvider::LoadFace(const String& file_name)
+{
+//    BM_Font *bm_face = new BM_Font();
+//    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 );
+
+//    URL file_url = file_name;
+
+//    bm_face->Face.Source = file_url.GetFileName();
+//    bm_face->Face.Directory = file_url.GetPath();
+
+//    return bm_face;
+    return 0;
+}
+
+// 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";
+
+//    BM_Font *bm_face = new BM_Font();
+//    FontParser parser( bm_face );
+//    StreamMemory* stream = new StreamMemory( data, data_length );
+//    stream->SetSourceURL( file_url );
+
+//    parser.Parse( stream );
+
+//    bm_face->Face.Source = file_url.GetFileName();
+//    bm_face->Face.Directory = file_url.GetPath();
+
+//    return bm_face;
+    return 0;
+}
+
+}
+}
+}

+ 65 - 10
Source/Core/FontDatabase.cpp

@@ -30,8 +30,7 @@
 #include <Rocket/Core/FontFamily.h>
 #include <Rocket/Core.h>
 #include <Rocket/Core/FreeType/FontProvider.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include <Rocket/Core/BitmapFont/FontProvider.h>
 
 namespace Rocket {
 namespace Core {
@@ -42,8 +41,6 @@ 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);
@@ -64,6 +61,9 @@ bool FontDatabase::Initialise()
 
         if(!FreeType::FontProvider::Initialise())
             return false;
+
+        if(!BitmapFont::FontProvider::Initialise())
+            return false;
 	}
 
 	return true;
@@ -74,6 +74,7 @@ void FontDatabase::Shutdown()
 	if (instance != NULL)
 	{
         FreeType::FontProvider::Shutdown();
+        BitmapFont::FontProvider::Shutdown();
 
 		delete instance;
 	}
@@ -82,25 +83,81 @@ void FontDatabase::Shutdown()
 // Loads a new font face.
 bool FontDatabase::LoadFontFace(const String& file_name)
 {
-    return FreeType::FontProvider::LoadFontFace(file_name);
+    FontProviderType font_provider_type = GetFontProviderType(file_name);
+
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(file_name);
+
+        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)
 {
-    return FreeType::FontProvider::LoadFontFace(file_name, family, style, weight);
+    FontProviderType font_provider_type = GetFontProviderType(file_name);
+
+    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(FontProviderType font_provider_type, const byte* data, int data_length)
 {
-    return FreeType::FontProvider::LoadFontFace(data, data_length);
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(data, data_length);
+
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(data, data_length);
+
+        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(FontProviderType font_provider_type, const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
 {
-    return FreeType::FontProvider::LoadFontFace(data, data_length, family, style, weight);
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(data, data_length, family, style, weight);
+
+        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.
@@ -114,8 +171,6 @@ FontFaceHandle* FontDatabase::GetFontFaceHandle(const String& family, const Stri
     {
         FontFaceHandle * face_handle = font_provider_table[ provider_index ]->GetFontFaceHandle(family, charset, style, weight, size);
 
-        Log::Message(Log::LT_WARNING, "%x", face_handle );
-
         if(face_handle)
         {
             return face_handle;

+ 10 - 201
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,167 +307,22 @@ 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;
+    /*if(rhs >= kerning.size())
+        return 0;
 
-	FT_Vector ft_kerning;
+    FontKerningList::const_iterator rhs_iterator = kerning.find(rhs);
+    if (rhs_iterator == kerning.end())
+        return 0;
 
-	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);
+    GlyphKerningList::const_iterator lhs_iterator = rhs_iterator->find(lhs);
+    if (lhs_iterator == (*rhs_iterator).end())
+        return 0;
 
-	if (ft_error != 0)
-		return 0;
+    return *lhs_iterator;*/
 
-	int kerning = ft_kerning.x >> 6;
-	return kerning;
+    return 0;
 }
 
 // Generates (or shares) a layer derived from a font effect.

+ 16 - 35
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,51 +52,44 @@ 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;
+    int GetCharacterWidth() const;
 
 	/// Returns the point size of this font face.
 	/// @return The face's point size.
-	int GetSize() const;
+    int GetSize() const;
 	/// Returns the pixel height of a lower-case x in this font face.
 	/// @return The height of a lower-case x.
-	int GetXHeight() const;
+    int GetXHeight() const;
 	/// Returns the default height between this font face's baselines.
 	/// @return The default line height.
-	int GetLineHeight() const;
+    int GetLineHeight() const;
 
 	/// Returns the font's baseline, as a pixel offset from the bottom of the font.
 	/// @return The font's baseline.
-	int GetBaseline() const;
+    int GetBaseline() const;
 
 	/// Returns the font's glyphs.
 	/// @return The font's glyphs.
-	const FontGlyphList& GetGlyphs() const;
+    const FontGlyphList& GetGlyphs() const;
 
 	/// Returns the width a string will take up if rendered with this handle.
 	/// @param[in] string The string to measure.
 	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning.
 	/// @return The width, in pixels, this string will occupy if rendered with this handle.
-	int GetStringWidth(const WString& string, word prior_character = 0) const;
+    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,43 +97,33 @@ 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.
-	const String& GetRawCharset() const;
+    const String& GetRawCharset() const;
 	/// Returns the font face's charset.
 	/// @return The font face's charset.
-	const UnicodeRangeList& GetCharset() const;
+    const UnicodeRangeList& GetCharset() const;
 
 protected:
 	/// Destroys the handle.
 	virtual void OnReferenceDeactivate();
-
-private:
-	void GenerateMetrics(void);
-
-	void BuildGlyphMap(const UnicodeRange& unicode_range);
-	void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph);
-
-	int GetKerning(word lhs, word rhs) const;
-
-	// Generates (or shares) a layer derived from a font effect.
-	FontFaceLayer* GenerateLayer(FontEffect* font_effect);
+    FontFaceLayer* GenerateLayer(FontEffect* font_effect);
+    virtual int GetKerning(word lhs, word rhs) const;
 
 	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) { }

+ 4 - 4
Source/Core/FreeType/FontFace.cpp

@@ -27,7 +27,7 @@
 
 #include "../precompiled.h"
 #include "FontFace.h"
-#include "../FontFaceHandle.h"
+#include "FontFaceHandle.h"
 #include "../../../Include/Rocket/Core/Log.h"
 
 namespace Rocket {
@@ -45,7 +45,7 @@ FontFace::~FontFace()
 }
 
 // Returns a handle for positioning and rendering this face at the given size.
-FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
+Rocket::Core::FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
 {
     UnicodeRangeList charset;
 
@@ -62,7 +62,7 @@ FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
             if (handles[i]->GetRawCharset() == _raw_charset)
             {
                 handles[i]->AddReference();
-                return handles[i];
+                return (Rocket::Core::FreeType::FontFaceHandle*)handles[i];
             }
         }
 
@@ -87,7 +87,7 @@ FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
             if (range_contained)
             {
                 handles[i]->AddReference();
-                return handles[i];
+                return (Rocket::Core::FreeType::FontFaceHandle*)handles[i];
             }
         }
     }

+ 3 - 4
Source/Core/FreeType/FontFace.h

@@ -34,14 +34,13 @@
 
 namespace Rocket {
 namespace Core {
-
-class FontFaceHandle;
-
 namespace FreeType {
 /**
     @author Peter Curry
  */
 
+class FontFaceHandle;
+
 class FontFace : public Rocket::Core::FontFace
 {
 public:
@@ -52,7 +51,7 @@ 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);
+    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.

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

@@ -1,566 +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 {
-
-//class FontEffectSort
-//{
-//public:
-//	bool operator()(const FontEffect* lhs, const FontEffect* rhs)
-//	{
-//		return lhs->GetZIndex() < rhs->GetZIndex();
-//	}
-//};
-
-//FontFaceHandle::FontFaceHandle()
-//{
-//	size = 0;
-//	average_advance = 0;
-//	x_height = 0;
-//	line_height = 0;
-//	baseline = 0;
-
-//	underline_position = 0;
-//	underline_thickness = 0;
-
-//	ft_face = NULL;
-
-//	base_layer = NULL;
-//}
-
-//FontFaceHandle::~FontFaceHandle()
-//{
-//	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
-//		delete[] i->bitmap_data;
-
-//	for (FontLayerMap::iterator i = layers.begin(); i != layers.end(); ++i)
-//		delete i->second;
-//}
-
-//// Initialises the handle so it is able to render text.
-//bool FontFaceHandle::Initialise(FT_Face ft_face, const String& _charset, int _size)
-//{
-//	size = _size;
-
-//	raw_charset = _charset;
-//	if (!UnicodeRange::BuildList(charset, raw_charset))
-//	{
-//		Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString());
-//		return false;
-//	}
-
-//	// Set the character size on the font face.
-//	FT_Error error = FT_Set_Char_Size(ft_face, 0, size << 6, 0, 0);
-//	if (error != 0)
-//	{
-//		Log::Message(Log::LT_ERROR, "Unable to set the character size '%d' on the font face '%s %s'.", size, ft_face->family_name, ft_face->style_name);
-//		return false;
-//	}
-
-//	this->ft_face = ft_face;
-
-//	// find the maximum character we are interested in
-//	max_codepoint = 0;
-//	for (size_t i = 0; i < charset.size(); ++i)
-//		max_codepoint = Math::Max(max_codepoint, charset[i].max_codepoint);
-
-//	// Construct the list of the characters specified by the charset.
-//	glyphs.resize(max_codepoint+1, FontGlyph());
-//	for (size_t i = 0; i < charset.size(); ++i)
-//		BuildGlyphMap(charset[i]);
-
-//	// Generate the metrics for the handle.
-//	GenerateMetrics();
-
-//	// Generate the default layer and layer configuration.
-//	base_layer = GenerateLayer(NULL);
-//	layer_configurations.push_back(LayerConfiguration());
-//	layer_configurations.back().push_back(base_layer);
-
-
-//	return true;
-//}
-
-//// Returns the point size of this font face.
-//int FontFaceHandle::GetSize() const
-//{
-//	return size;
-//}
-
-//// Returns the average advance of all glyphs in this font face.
-//int FontFaceHandle::GetCharacterWidth() const
-//{
-//	return average_advance;
-//}
-
-//// Returns the pixel height of a lower-case x in this font face.
-//int FontFaceHandle::GetXHeight() const
-//{
-//	return x_height;
-//}
-
-//// Returns the default height between this font face's baselines.
-//int FontFaceHandle::GetLineHeight() const
-//{
-//	return line_height;
-//}
-
-//// Returns the font's baseline.
-//int FontFaceHandle::GetBaseline() const
-//{
-//	return baseline;
-//}
-
-//// Returns the font's glyphs.
-//const FontGlyphList& FontFaceHandle::GetGlyphs() const
-//{
-//	return glyphs;
-//}
-
-//// Returns the width a string will take up if rendered with this handle.
-//int FontFaceHandle::GetStringWidth(const WString& string, word prior_character) const
-//{
-//	int width = 0;
-
-//	for (size_t i = 0; i < string.Length(); i++)
-//	{
-//		word character_code = string[i];
-
-//		if (character_code >= glyphs.size())
-//			continue;
-//		const FontGlyph &glyph = glyphs[character_code];
-
-//		// Adjust the cursor for the kerning between this character and the previous one.
-//		if (prior_character != 0)
-//			width += GetKerning(prior_character, string[i]);
-//		// Adjust the cursor for this character's advance.
-//		width += glyph.advance;
-
-//		prior_character = character_code;
-//	}
-
-//	return width;
-//}
-
-//// Generates, if required, the layer configuration for a given array of font effects.
-//int FontFaceHandle::GenerateLayerConfiguration(FontEffectMap& font_effects)
-//{
-//	if (font_effects.empty())
-//		return 0;
-
-//	// Prepare a list of effects, sorted by z-index.
-//	FontEffectList sorted_effects;
-//	for (FontEffectMap::const_iterator i = font_effects.begin(); i != font_effects.end(); ++i)
-//		sorted_effects.push_back(i->second);
-
-//	std::sort(sorted_effects.begin(), sorted_effects.end(), FontEffectSort());
-
-//	// Check each existing configuration for a match with this arrangement of effects.
-//	int configuration_index = 1;
-//	for (; configuration_index < (int) layer_configurations.size(); ++configuration_index)
-//	{
-//		const LayerConfiguration& configuration = layer_configurations[configuration_index];
-
-//		// Check the size is correct. For a math, there should be one layer in the configuration
-//		// plus an extra for the base layer.
-//		if (configuration.size() != sorted_effects.size() + 1)
-//			continue;
-
-//		// Check through each layer, checking it was created by the same effect as the one we're
-//		// checking.
-//		size_t effect_index = 0;
-//		for (size_t i = 0; i < configuration.size(); ++i)
-//		{
-//			// Skip the base layer ...
-//			if (configuration[i]->GetFontEffect() == NULL)
-//				continue;
-
-//			// If the ith layer's effect doesn't match the equivalent effect, then this
-//			// configuration can't match.
-//			if (configuration[i]->GetFontEffect() != sorted_effects[effect_index])
-//				break;
-
-//			// Check the next one ...
-//			++effect_index;
-//		}
-
-//		if (effect_index == sorted_effects.size())
-//			return configuration_index;
-//	}
-
-//	// No match, so we have to generate a new layer configuration.
-//	layer_configurations.push_back(LayerConfiguration());
-//	LayerConfiguration& layer_configuration = layer_configurations.back();
-
-//	bool added_base_layer = false;
-
-//	for (size_t i = 0; i < sorted_effects.size(); ++i)
-//	{
-//		if (!added_base_layer &&
-//			sorted_effects[i]->GetZIndex() >= 0)
-//		{
-//			layer_configuration.push_back(base_layer);
-//			added_base_layer = true;
-//		}
-
-//		layer_configuration.push_back(GenerateLayer(sorted_effects[i]));
-//	}
-
-//	// Add the base layer now if we still haven't added it.
-//	if (!added_base_layer)
-//		layer_configuration.push_back(base_layer);
-
-//	return (int) (layer_configurations.size() - 1);
-//}
-
-//// Generates the texture data for a layer (for the texture database).
-//bool FontFaceHandle::GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id)
-//{
-//	FontLayerMap::iterator layer_iterator = layers.find(layer_id);
-//	if (layer_iterator == layers.end())
-//		return false;
-
-//	return layer_iterator->second->GenerateTexture(texture_data, texture_dimensions, texture_id);
-//}
-
-//// Generates the geometry required to render a single line of text.
-//int FontFaceHandle::GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration_index) const
-//{
-//	int geometry_index = 0;
-//	int line_width = 0;
-
-//	ROCKET_ASSERT(layer_configuration_index >= 0);
-//	ROCKET_ASSERT(layer_configuration_index < (int) layer_configurations.size());
-
-//	// Fetch the requested configuration and generate the geometry for each one.
-//	const LayerConfiguration& layer_configuration = layer_configurations[layer_configuration_index];
-//	for (size_t i = 0; i < layer_configuration.size(); ++i)
-//	{
-//		FontFaceLayer* layer = layer_configuration[i];
-
-//		Colourb layer_colour;
-//		if (layer == base_layer)
-//			layer_colour = colour;
-//		else
-//			layer_colour = layer->GetColour();
-
-//		// Resize the geometry list if required.
-//		if ((int) geometry.size() < geometry_index + layer->GetNumTextures())
-//			geometry.resize(geometry_index + layer->GetNumTextures());
-
-//		// Bind the textures to the geometries.
-//		for (int i = 0; i < layer->GetNumTextures(); ++i)
-//			geometry[geometry_index + i].SetTexture(layer->GetTexture(i));
-
-//		line_width = 0;
-//		word prior_character = 0;
-
-//		const word* string_iterator = string.CString();
-//		const word* string_end = string.CString() + string.Length();
-
-//		for (; string_iterator != string_end; string_iterator++)
-//		{
-//			if (*string_iterator >= glyphs.size())
-//				continue;
-//			const FontGlyph &glyph = glyphs[*string_iterator];
-
-//			// Adjust the cursor for the kerning between this character and the previous one.
-//			if (prior_character != 0)
-//				line_width += GetKerning(prior_character, *string_iterator);
-
-//			layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour);
-
-//			line_width += glyph.advance;
-//			prior_character = *string_iterator;
-//		}
-
-//		geometry_index += layer->GetNumTextures();
-//	}
-
-//	// Cull any excess geometry from a previous generation.
-//	geometry.resize(geometry_index);
-
-//	return line_width;
-//}
-
-//// Generates the geometry required to render a line above, below or through a line of text.
-//void FontFaceHandle::GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const
-//{
-//	std::vector< Vertex >& line_vertices = geometry->GetVertices();
-//	std::vector< int >& line_indices = geometry->GetIndices();
-
-//	float offset;
-//	switch (height)
-//	{
-//		case Font::UNDERLINE:			offset = -underline_position; break;
-//		case Font::OVERLINE:			// where to place? offset = -line_height - underline_position; break;
-//		case Font::STRIKE_THROUGH:		// where to place? offset = -line_height * 0.5f; break;
-//		default:						return;
-//	}
-
-//	line_vertices.resize(line_vertices.size() + 4);
-//	line_indices.resize(line_indices.size() + 6);
-//	GeometryUtilities::GenerateQuad(&line_vertices[0] + (line_vertices.size() - 4), &line_indices[0] + (line_indices.size() - 6), Vector2f(position.x, position.y + offset), Vector2f((float) width, underline_thickness), colour, (int)line_vertices.size() - 4);
-//}
-
-//// Returns the font face's raw charset (the charset range as a string).
-//const String& FontFaceHandle::GetRawCharset() const
-//{
-//	return raw_charset;
-//}
-
-//// Returns the font face's charset.
-//const UnicodeRangeList& FontFaceHandle::GetCharset() const
-//{
-//	return charset;
-//}
-
-//// Destroys the handle.
-//void FontFaceHandle::OnReferenceDeactivate()
-//{
-//	delete this;
-//}
-
-//void FontFaceHandle::GenerateMetrics()
-//{
-//	line_height = ft_face->size->metrics.height >> 6;
-//	baseline = line_height - (ft_face->size->metrics.ascender >> 6);
-
-//	underline_position = FT_MulFix(ft_face->underline_position, ft_face->size->metrics.y_scale) / float(1 << 6);
-//	underline_thickness = FT_MulFix(ft_face->underline_thickness, ft_face->size->metrics.y_scale) / float(1 << 6);
-//	underline_thickness = Math::Max(underline_thickness, 1.0f);
-
-//	average_advance = 0;
-//	unsigned int num_visible_glyphs = 0;
-//	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
-//	{
-//		if (i->advance)
-//		{
-//			average_advance += i->advance;
-//			num_visible_glyphs++;
-//		}
-//	}
-
-//	// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
-//	if (num_visible_glyphs)
-//		average_advance = Math::RealToInteger((float) average_advance / (num_visible_glyphs * 0.9f));
-
-//	// Determine the x-height of this font face.
-//	word x = (word) 'x';
-//	int index = FT_Get_Char_Index(ft_face, x);
-//	if (FT_Load_Glyph(ft_face, index, 0) == 0)
-//		x_height = ft_face->glyph->metrics.height >> 6;
-//	else
-//		x_height = 0;
-//}
-
-//void FontFaceHandle::BuildGlyphMap(const UnicodeRange& unicode_range)
-//{
-//	for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code)
-//	{
-//		int index = FT_Get_Char_Index(ft_face, character_code);
-//		if (index != 0)
-//		{
-//			FT_Error error = FT_Load_Glyph(ft_face, index, 0);
-//			if (error != 0)
-//			{
-//				Log::Message(Log::LT_WARNING, "Unable to load glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
-//				continue;
-//			}
-
-//			error = FT_Render_Glyph(ft_face->glyph, FT_RENDER_MODE_NORMAL);
-//			if (error != 0)
-//			{
-//				Log::Message(Log::LT_WARNING, "Unable to render glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
-//				continue;
-//			}
-
-//			FontGlyph glyph;
-//			glyph.character = character_code;
-//			BuildGlyph(glyph, ft_face->glyph);
-//			glyphs[character_code] = glyph;
-//		}
-//	}
-//}
-
-//void FontFaceHandle::BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph)
-//{
-//	// Set the glyph's dimensions.
-//	glyph.dimensions.x = ft_glyph->metrics.width >> 6;
-//	glyph.dimensions.y = ft_glyph->metrics.height >> 6;
-
-//	// Set the glyph's bearing.
-//	glyph.bearing.x = ft_glyph->metrics.horiBearingX >> 6;
-//	glyph.bearing.y = ft_glyph->metrics.horiBearingY >> 6;
-
-//	// Set the glyph's advance.
-//	glyph.advance = ft_glyph->metrics.horiAdvance >> 6;
-
-//	// Set the glyph's bitmap dimensions.
-//	glyph.bitmap_dimensions.x = ft_glyph->bitmap.width;
-//	glyph.bitmap_dimensions.y = ft_glyph->bitmap.rows;
-
-//	// Copy the glyph's bitmap data from the FreeType glyph handle to our glyph handle.
-//	if (glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y != 0)
-//	{
-//		// Check the pixel mode is supported.
-//		if (ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
-//			ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
-//		{
-//			glyph.bitmap_data = NULL;
-//			Log::Message(Log::LT_WARNING, "Unable to render glyph on the font face '%s %s'; unsupported pixel mode (%d).", ft_glyph->face->family_name, ft_glyph->face->style_name, ft_glyph->bitmap.pixel_mode);
-//		}
-//		else
-//		{
-//			glyph.bitmap_data = new byte[glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y];
-
-//			byte* source_bitmap = ft_glyph->bitmap.buffer;
-//			byte* destination_bitmap = glyph.bitmap_data;
-
-//			// Copy the bitmap data into the newly-allocated space on our glyph.
-//			switch (ft_glyph->bitmap.pixel_mode)
-//			{
-//				// Unpack 1-bit data into 8-bit.
-//				case FT_PIXEL_MODE_MONO:
-//				{
-//					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
-//					{
-//						int mask = 0x80;
-//						byte* source_byte = source_bitmap;
-//						for (int j = 0; j < glyph.bitmap_dimensions.x; ++j)
-//						{
-//							if ((*source_byte & mask) == mask)
-//								destination_bitmap[j] = 255;
-//							else
-//								destination_bitmap[j] = 0;
-
-//							mask >>= 1;
-//							if (mask <= 0)
-//							{
-//								mask = 0x80;
-//								++source_byte;
-//							}
-//						}
-
-//						destination_bitmap += glyph.bitmap_dimensions.x;
-//						source_bitmap += ft_glyph->bitmap.pitch;
-//					}
-//				}
-//				break;
-
-//				// Directly copy 8-bit data.
-//				case FT_PIXEL_MODE_GRAY:
-//				{
-//					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
-//					{
-//						memcpy(destination_bitmap, source_bitmap, glyph.bitmap_dimensions.x);
-//						destination_bitmap += glyph.bitmap_dimensions.x;
-//						source_bitmap += ft_glyph->bitmap.pitch;
-//					}
-//				}
-//				break;
-//			}
-//		}
-//	}
-//	else
-//		glyph.bitmap_data = NULL;
-//}
-
-//int FontFaceHandle::GetKerning(word lhs, word rhs) const
-//{
-//	if (!FT_HAS_KERNING(ft_face))
-//		return 0;
-
-//	FT_Vector ft_kerning;
-
-//	FT_Error ft_error = FT_Get_Kerning(ft_face,
-//		FT_Get_Char_Index(ft_face, lhs), FT_Get_Char_Index(ft_face, rhs),
-//		FT_KERNING_DEFAULT, &ft_kerning);
-
-//	if (ft_error != 0)
-//		return 0;
-
-//	int kerning = ft_kerning.x >> 6;
-//	return kerning;
-//}
-
-//// Generates (or shares) a layer derived from a font effect.
-//FontFaceLayer* FontFaceHandle::GenerateLayer(FontEffect* font_effect)
-//{
-//	// See if this effect has been instanced before, as part of a different configuration.
-//	FontLayerMap::iterator i = layers.find(font_effect);
-//	if (i != layers.end())
-//		return i->second;
-
-//	FontFaceLayer* layer = new FontFaceLayer();
-//	layers[font_effect] = layer;
-
-//	if (font_effect == NULL)
-//	{
-//		layer->Initialise(this);
-//	}
-//	else
-//	{
-//		// Determine which, if any, layer the new layer should copy its geometry and textures from.
-//		FontFaceLayer* clone = NULL;
-//		bool deep_clone = true;
-//		String generation_key;
-
-//		if (!font_effect->HasUniqueTexture())
-//		{
-//			clone = base_layer;
-//			deep_clone = false;
-//		}
-//		else
-//		{
-//			generation_key = font_effect->GetName() + ";" + font_effect->GetGenerationKey();
-//			FontLayerCache::iterator cache_iterator = layer_cache.find(generation_key);
-//			if (cache_iterator != layer_cache.end())
-//				clone = cache_iterator->second;
-//		}
-
-//		// Create a new layer.
-//		layer->Initialise(this, font_effect, clone, deep_clone);
-
-//		// Cache the layer in the layer cache if it generated its own textures (ie, didn't clone).
-//		if (clone == NULL)
-//			layer_cache[generation_key] = layer;
-//	}
-
-//	return layer;
-//}
-
-//}
-//}
+/*
+ * 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 - 182
Source/Core/FreeType/FontFaceHandle.h

@@ -1,182 +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 ROCKETCOREFONTFACEHANDLE_H
-//#define ROCKETCOREFONTFACEHANDLE_H
-
-//#include "../../Include/Rocket/Core/ReferenceCountable.h"
-//#include "UnicodeRange.h"
-//#include "../../Include/Rocket/Core/Font.h"
-//#include "../../Include/Rocket/Core/FontEffect.h"
-//#include "../../Include/Rocket/Core/FontGlyph.h"
-//#include "../../Include/Rocket/Core/Geometry.h"
-//#include "../../Include/Rocket/Core/String.h"
-//#include "../../Include/Rocket/Core/Texture.h"
-//#include <ft2build.h>
-//#include FT_FREETYPE_H
-
-//namespace Rocket {
-//namespace Core {
-
-//class FontFaceLayer;
-
-///**
-//	@author Peter Curry
-// */
-
-//class FontFaceHandle : public ReferenceCountable
-//{
-//public:
-//	FontFaceHandle();
-//	virtual ~FontFaceHandle();
-
-//	/// Initialises the handle so it is able to render text.
-//	/// @param[in] ft_face The FreeType face that this handle is rendering.
-//	/// @param[in] charset The comma-separated list of unicode ranges this handle must support.
-//	/// @param[in] size The size, in points, of the face this handle should render at.
-//	/// @return True if the handle initialised successfully and is ready for rendering, false if an error occured.
-//	bool Initialise(FT_Face ft_face, const String& charset, int size);
-
-//	/// Returns the average advance of all glyphs in this font face.
-//	/// @return An approximate width of the characters in this font face.
-//	int GetCharacterWidth() const;
-
-//	/// Returns the point size of this font face.
-//	/// @return The face's point size.
-//	int GetSize() const;
-//	/// Returns the pixel height of a lower-case x in this font face.
-//	/// @return The height of a lower-case x.
-//	int GetXHeight() const;
-//	/// Returns the default height between this font face's baselines.
-//	/// @return The default line height.
-//	int GetLineHeight() const;
-
-//	/// Returns the font's baseline, as a pixel offset from the bottom of the font.
-//	/// @return The font's baseline.
-//	int GetBaseline() const;
-
-//	/// Returns the font's glyphs.
-//	/// @return The font's glyphs.
-//	const FontGlyphList& GetGlyphs() const;
-
-//	/// Returns the width a string will take up if rendered with this handle.
-//	/// @param[in] string The string to measure.
-//	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning.
-//	/// @return The width, in pixels, this string will occupy if rendered with this handle.
-//	int GetStringWidth(const WString& string, word prior_character = 0) const;
-
-//	/// Generates, if required, the layer configuration for a given array of font effects.
-//	/// @param[in] font_effects The list of font effects to generate the configuration for.
-//	/// @return The index to use when generating geometry using this configuration.
-//	int GenerateLayerConfiguration(FontEffectMap& font_effects);
-//	/// Generates the texture data for a layer (for the texture database).
-//	/// @param[out] texture_data The pointer to be set to the generated texture data.
-//	/// @param[out] texture_dimensions The dimensions of the texture.
-//	/// @param[in] layer_id The id of the layer to request the texture data from.
-//	/// @param[in] texture_id The index of the texture within the layer to generate.
-//	bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id);
-
-//	/// Generates the geometry required to render a single line of text.
-//	/// @param[out] geometry An array of geometries to generate the geometry into.
-//	/// @param[in] string The string to render.
-//	/// @param[in] position The position of the baseline of the first character to render.
-//	/// @param[in] colour The colour to render the text.
-//	/// @return The width, in pixels, of the string geometry.
-//	int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const;
-//	/// Generates the geometry required to render a line above, below or through a line of text.
-//	/// @param[out] geometry The geometry to append the newly created geometry into.
-//	/// @param[in] position The position of the baseline of the lined text.
-//	/// @param[in] width The width of the string to line.
-//	/// @param[in] height The height to render the line at.
-//	/// @param[in] colour The colour to draw the line in.
-//	void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const;
-
-//	/// Returns the font face's raw charset (the charset range as a string).
-//	/// @return The font face's charset.
-//	const String& GetRawCharset() const;
-//	/// Returns the font face's charset.
-//	/// @return The font face's charset.
-//	const UnicodeRangeList& GetCharset() const;
-
-//protected:
-//	/// Destroys the handle.
-//	virtual void OnReferenceDeactivate();
-
-//private:
-//	void GenerateMetrics(void);
-
-//	void BuildGlyphMap(const UnicodeRange& unicode_range);
-//	void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph);
-
-//	int GetKerning(word lhs, word rhs) const;
-
-//	// Generates (or shares) a layer derived from a font effect.
-//	FontFaceLayer* GenerateLayer(FontEffect* font_effect);
-
-//	typedef std::vector< int > GlyphKerningList;
-//	typedef std::vector< GlyphKerningList > FontKerningList;
-
-//	FT_Face ft_face;
-
-//	FontGlyphList glyphs;
-
-//	typedef std::map< const FontEffect*, FontFaceLayer* > FontLayerMap;
-//	typedef std::map< String, FontFaceLayer* > FontLayerCache;
-//	typedef std::vector< FontFaceLayer* > LayerConfiguration;
-//	typedef std::vector< LayerConfiguration > LayerConfigurationList;
-
-//	// The list of all font layers, index by the effect that instanced them.
-//	FontFaceLayer* base_layer;
-//	FontLayerMap layers;
-//	// Each font layer that generated geometry or textures, indexed by the respective generation
-//	// key.
-//	FontLayerCache layer_cache;
-
-//	// All configurations currently in use on this handle. New configurations will be generated as
-//	// required.
-//	LayerConfigurationList layer_configurations;
-
-//	// The average advance (in pixels) of all of this face's glyphs.
-//	int average_advance;
-
-//	int size;
-//	int x_height;
-//	int line_height;
-//	int baseline;
-
-//	float underline_position;
-//	float underline_thickness;
-
-//	String raw_charset;
-//	UnicodeRangeList charset;
-//	unsigned int max_codepoint;
-//};
-
-//}
-//}
-
-//#endif
+/*
+ * 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

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

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

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

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

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

@@ -60,6 +60,8 @@ bool FontProvider::Initialise()
     {
         new FontProvider();
 
+        FontDatabase::AddFontProvider(instance);
+
         FT_Error result = FT_Init_FreeType(&ft_library);
         if (result != 0)
         {