From 78571d6dd5820151e54cfb9d3ea607abbb62301c Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Sat, 29 Aug 2015 10:46:25 +0200 Subject: [PATCH 01/13] Changes in FontDatabase --- Build/cmake/FileList.cmake | 14 +- Include/Rocket/Core/FontDatabase.h | 27 +- {Source => Include/Rocket}/Core/FontFamily.h | 4 +- Include/Rocket/Core/FontProvider.h | 72 +++ Include/Rocket/Core/FreeType/FontProvider.h | 112 ++++ Source/Core/FontDatabase.cpp | 198 ++----- Source/Core/FontFamily.cpp | 6 +- Source/Core/FontProvider.cpp | 50 ++ Source/Core/FreeType/FontFace.cpp | 160 ++++++ Source/Core/FreeType/FontFace.h | 82 +++ Source/Core/FreeType/FontFaceHandle.cpp | 566 +++++++++++++++++++ Source/Core/FreeType/FontFaceHandle.h | 182 ++++++ Source/Core/FreeType/FontFaceLayer.cpp | 242 ++++++++ Source/Core/FreeType/FontFaceLayer.h | 142 +++++ Source/Core/FreeType/FontFamily.cpp | 79 +++ Source/Core/FreeType/FontFamily.h | 81 +++ Source/Core/FreeType/FontProvider.cpp | 267 +++++++++ Source/Debugger/Plugin.cpp | 4 +- 18 files changed, 2109 insertions(+), 179 deletions(-) rename {Source => Include/Rocket}/Core/FontFamily.h (95%) create mode 100644 Include/Rocket/Core/FontProvider.h create mode 100644 Include/Rocket/Core/FreeType/FontProvider.h create mode 100644 Source/Core/FontProvider.cpp create mode 100644 Source/Core/FreeType/FontFace.cpp create mode 100644 Source/Core/FreeType/FontFace.h create mode 100644 Source/Core/FreeType/FontFaceHandle.cpp create mode 100644 Source/Core/FreeType/FontFaceHandle.h create mode 100644 Source/Core/FreeType/FontFaceLayer.cpp create mode 100644 Source/Core/FreeType/FontFaceLayer.h create mode 100644 Source/Core/FreeType/FontFamily.cpp create mode 100644 Source/Core/FreeType/FontFamily.h create mode 100644 Source/Core/FreeType/FontProvider.cpp diff --git a/Build/cmake/FileList.cmake b/Build/cmake/FileList.cmake index 776c46adc..8bf5df20d 100644 --- a/Build/cmake/FileList.cmake +++ b/Build/cmake/FileList.cmake @@ -39,7 +39,10 @@ set(Core_HDR_FILES ${PROJECT_SOURCE_DIR}/Source/Core/FontFace.h ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceHandle.h ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.h - ${PROJECT_SOURCE_DIR}/Source/Core/FontFamily.h + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.h + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.h + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceLayer.h + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.h ${PROJECT_SOURCE_DIR}/Source/Core/GeometryDatabase.h ${PROJECT_SOURCE_DIR}/Source/Core/LayoutBlockBox.h ${PROJECT_SOURCE_DIR}/Source/Core/LayoutBlockBoxSpace.h @@ -128,7 +131,10 @@ set(Core_PUB_HDR_FILES ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontDatabase.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffect.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffectInstancer.h + ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontFamily.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontGlyph.h + ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontProvider.h + ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FreeType/FontProvider.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/Geometry.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/GeometryUtilities.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/Header.h @@ -233,6 +239,12 @@ set(Core_SRC_FILES ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceHandle.cpp ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.cpp ${PROJECT_SOURCE_DIR}/Source/Core/FontFamily.cpp + ${PROJECT_SOURCE_DIR}/Source/Core/FontProvider.cpp + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.cpp + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.cpp + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceLayer.cpp + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.cpp + ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontProvider.cpp ${PROJECT_SOURCE_DIR}/Source/Core/Geometry.cpp ${PROJECT_SOURCE_DIR}/Source/Core/GeometryDatabase.cpp ${PROJECT_SOURCE_DIR}/Source/Core/GeometryUtilities.cpp diff --git a/Include/Rocket/Core/FontDatabase.h b/Include/Rocket/Core/FontDatabase.h index c1353050e..142525867 100644 --- a/Include/Rocket/Core/FontDatabase.h +++ b/Include/Rocket/Core/FontDatabase.h @@ -31,6 +31,7 @@ #include "StringUtilities.h" #include "Header.h" #include "Font.h" +#include "FontProvider.h" namespace Rocket { namespace Core { @@ -49,6 +50,13 @@ class PropertyDictionary; class ROCKETCORE_API FontDatabase { public: + + enum FontProviderType + { + FreeType = 0, + Bitmap + }; + static bool Initialise(); static void Shutdown(); @@ -67,7 +75,7 @@ class ROCKETCORE_API FontDatabase /// @param[in] data The font data. /// @param[in] data_length Length of the data. /// @return True if the face was loaded successfully, false otherwise. - static bool LoadFontFace(const byte* data, int data_length); + static bool LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length); /// Adds a new font face to the database, loading from memory. /// @param[in] data The font data. /// @param[in] data_length Length of the data. @@ -75,7 +83,7 @@ class ROCKETCORE_API FontDatabase /// @param[in] style The style of the face (normal or italic). /// @param[in] weight The weight of the face (normal or bold). /// @return True if the face was loaded successfully, false otherwise. - static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight); + static bool LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight); /// Returns a handle to a font face that can be used to position and render text. This will return the closest match /// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a @@ -99,20 +107,17 @@ class ROCKETCORE_API FontDatabase /// @param[in] The effect to release. static void ReleaseFontEffect(const FontEffect* effect); + static void AddFontProvider(FontProvider * provider); + + static void RemoveFontProvider(FontProvider * provider); + private: FontDatabase(void); ~FontDatabase(void); - // Adds a loaded face to the appropriate font family. - bool AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream); - // Loads a FreeType face. - void* LoadFace(const String& file_name); - // Loads a FreeType face from memory. - void* LoadFace(const byte* data, int data_length, const String& source, bool local_data); - - typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap; - FontFamilyMap font_families; + typedef std::vector< FontProvider *> FontProviderTable; + static FontProviderTable font_provider_table; static FontDatabase* instance; }; diff --git a/Source/Core/FontFamily.h b/Include/Rocket/Core/FontFamily.h similarity index 95% rename from Source/Core/FontFamily.h rename to Include/Rocket/Core/FontFamily.h index 6051a04b2..fe9234a40 100644 --- a/Source/Core/FontFamily.h +++ b/Include/Rocket/Core/FontFamily.h @@ -28,7 +28,7 @@ #ifndef ROCKETCOREFONTFAMILY_H #define ROCKETCOREFONTFAMILY_H -#include "../../Include/Rocket/Core/Font.h" +#include "Font.h" #include #include FT_FREETYPE_H @@ -54,7 +54,7 @@ class FontFamily /// @param[in] weight The weight of the new face. /// @param[in] release_stream True if the application must free the face's memory stream. /// @return True if the face was loaded successfully, false otherwise. - bool AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream); + bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream); /// Returns a handle to the most appropriate font in the family, at the correct size. /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. diff --git a/Include/Rocket/Core/FontProvider.h b/Include/Rocket/Core/FontProvider.h new file mode 100644 index 000000000..ec162c4c9 --- /dev/null +++ b/Include/Rocket/Core/FontProvider.h @@ -0,0 +1,72 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef ROCKETCOREFONTPROVIDER_H +#define ROCKETCOREFONTPROVIDER_H + +#include +#include +#include + +namespace Rocket { +namespace Core { + +class FontFaceHandle; +class FontFamily; + +/** + The font database contains all font families currently in use by Rocket. + @author Peter Curry + */ + +class ROCKETCORE_API FontProvider +{ +public: + + /// Returns a handle to a font face that can be used to position and render text. This will return the closest match + /// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a + /// valid handle. + /// @param[in] family The family of the desired font handle. + /// @param[in] charset The set of characters required in the font face, as a comma-separated list of unicode ranges. + /// @param[in] style The style of the desired font handle. + /// @param[in] weight The weight of the desired font handle. + /// @param[in] size The size of desired handle, in points. + /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise. + virtual FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) = 0; + +protected: + + FontFamily* GetFontFamily(const String& family); + + typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap; + FontFamilyMap font_families; +}; + +} +} + +#endif diff --git a/Include/Rocket/Core/FreeType/FontProvider.h b/Include/Rocket/Core/FreeType/FontProvider.h new file mode 100644 index 000000000..c684bf63f --- /dev/null +++ b/Include/Rocket/Core/FreeType/FontProvider.h @@ -0,0 +1,112 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef ROCKETCOREFREETYPEFONTPROVIDER_H +#define ROCKETCOREFREETYPEFONTPROVIDER_H + +#include +#include +#include + +namespace Rocket { +namespace Core { + + +class FontEffect; +class FontFaceHandle; +class PropertyDictionary; + +namespace FreeType { + +class FontFamily; + +/** + The font database contains all font families currently in use by Rocket. + @author Peter Curry + */ + +class ROCKETCORE_API FontProvider : public Rocket::Core::FontProvider +{ +public: + static bool Initialise(); + static void Shutdown(); + + /// Adds a new font face to the database. The face's family, style and weight will be determined from the face itself. + /// @param[in] file_name The file to load the face from. + /// @return True if the face was loaded successfully, false otherwise. + static bool LoadFontFace(const String& file_name); + /// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself. + /// @param[in] file_name The file to load the face from. + /// @param[in] family The family to add the face to. + /// @param[in] style The style of the face (normal or italic). + /// @param[in] weight The weight of the face (normal or bold). + /// @return True if the face was loaded successfully, false otherwise. + static bool LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight); + /// Adds a new font face to the database, loading from memory. The face's family, style and weight will be determined from the face itself. + /// @param[in] data The font data. + /// @param[in] data_length Length of the data. + /// @return True if the face was loaded successfully, false otherwise. + static bool LoadFontFace(const byte* data, int data_length); + /// Adds a new font face to the database, loading from memory. + /// @param[in] data The font data. + /// @param[in] data_length Length of the data. + /// @param[in] family The family to add the face to. + /// @param[in] style The style of the face (normal or italic). + /// @param[in] weight The weight of the face (normal or bold). + /// @return True if the face was loaded successfully, false otherwise. + static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight); + + /// Returns a handle to a font face that can be used to position and render text. This will return the closest match + /// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a + /// valid handle. + /// @param[in] family The family of the desired font handle. + /// @param[in] charset The set of characters required in the font face, as a comma-separated list of unicode ranges. + /// @param[in] style The style of the desired font handle. + /// @param[in] weight The weight of the desired font handle. + /// @param[in] size The size of desired handle, in points. + /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise. + virtual FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size); + +private: + FontProvider(void); + ~FontProvider(void); + + // Adds a loaded face to the appropriate font family. + bool AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream); + // Loads a FreeType face. + void* LoadFace(const String& file_name); + // Loads a FreeType face from memory. + void* LoadFace(const byte* data, int data_length, const String& source, bool local_data); + + static FontProvider* instance; +}; + +} +} +} + +#endif diff --git a/Source/Core/FontDatabase.cpp b/Source/Core/FontDatabase.cpp index e481aac7d..bf8aae7d5 100644 --- a/Source/Core/FontDatabase.cpp +++ b/Source/Core/FontDatabase.cpp @@ -26,9 +26,10 @@ */ #include "precompiled.h" -#include "../../Include/Rocket/Core/FontDatabase.h" -#include "FontFamily.h" -#include "../../Include/Rocket/Core.h" +#include +#include +#include +#include #include #include FT_FREETYPE_H @@ -60,13 +61,8 @@ bool FontDatabase::Initialise() { new FontDatabase(); - FT_Error result = FT_Init_FreeType(&ft_library); - if (result != 0) - { - Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result); - Shutdown(); - return false; - } + if(!FreeType::FontProvider::Initialise()) + return false; } return true; @@ -76,14 +72,7 @@ void FontDatabase::Shutdown() { if (instance != NULL) { - for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i) - delete (*i).second; - - if (ft_library != NULL) - { - FT_Done_FreeType(ft_library); - ft_library = NULL; - } + FreeType::FontProvider::Shutdown(); delete instance; } @@ -92,105 +81,45 @@ void FontDatabase::Shutdown() // Loads a new font face. bool FontDatabase::LoadFontFace(const String& file_name) { - FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); - return false; - } - - Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; - - if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return false; - } + return FreeType::FontProvider::LoadFontFace(file_name); } // Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself. bool FontDatabase::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight) { - FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); - return false; - } - - if (instance->AddFace(ft_face, family, style, weight, true)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return false; - } + return FreeType::FontProvider::LoadFontFace(file_name, family, style, weight); } // Adds a new font face to the database, loading from memory. -bool FontDatabase::LoadFontFace(const byte* data, int data_length) +bool FontDatabase::LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length) { - FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); - return false; - } - - Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; - - if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return false; - } + return FreeType::FontProvider::LoadFontFace(data, data_length); } // Adds a new font face to the database, loading from memory, ignoring any family, style and weight information stored in the face itself. -bool FontDatabase::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight) +bool FontDatabase::LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight) { - FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); - return false; - } - - if (instance->AddFace(ft_face, family, style, weight, false)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return false; - } + return FreeType::FontProvider::LoadFontFace(data, data_length, family, style, weight); } // Returns a handle to a font face that can be used to position and render text. FontFaceHandle* FontDatabase::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) { - FontFamilyMap::iterator iterator = instance->font_families.find(family); - if (iterator == instance->font_families.end()) - return NULL; + size_t provider_index, provider_count; - return (*iterator).second->GetFaceHandle(charset, style, weight, size); + provider_count = font_provider_table.size(); + + for(provider_index = 0; provider_index < provider_count; ++provider_index) + { + FontFaceHandle * face_handle = font_provider_table[ provider_index ]->GetFontFaceHandle(family, charset, style, weight, size); + + if(face_handle) + { + return face_handle; + } + } + + return NULL; } // Returns a font effect, either a newly-instanced effect from the factory or an identical shared @@ -255,72 +184,21 @@ void FontDatabase::ReleaseFontEffect(const FontEffect* effect) } } -// Adds a loaded face to the appropriate font family. -bool FontDatabase::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream) +void FontDatabase::AddFontProvider(FontProvider * provider) { - FontFamily* font_family = NULL; - FontFamilyMap::iterator iterator = instance->font_families.find(family); - if (iterator != instance->font_families.end()) - font_family = (*iterator).second; - else - { - font_family = new FontFamily(family); - instance->font_families[family] = font_family; - } - - return font_family->AddFace((FT_Face) face, style, weight, release_stream); + instance->font_provider_table.push_back(provider); } -// Loads a FreeType face. -void* FontDatabase::LoadFace(const String& file_name) +void FontDatabase::RemoveFontProvider(FontProvider * provider) { - FileInterface* file_interface = GetFileInterface(); - FileHandle handle = file_interface->Open(file_name); - - if (!handle) - { - return NULL; - } - - size_t length = file_interface->Length(handle); - - FT_Byte* buffer = new FT_Byte[length]; - file_interface->Read(buffer, length, handle); - file_interface->Close(handle); - - return LoadFace(buffer, (int)length, file_name, true); -} - -// Loads a FreeType face from memory. -void* FontDatabase::LoadFace(const byte* data, int data_length, const String& source, bool local_data) -{ - FT_Face face = NULL; - int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face); - if (error != 0) - { - Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString()); - if (local_data) - delete[] data; - - return NULL; - } - - // Initialise the character mapping on the face. - if (face->charmap == NULL) - { - FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); - if (face->charmap == NULL) - { - Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString()); - FT_Done_Face(face); - if (local_data) - delete[] data; - - return NULL; - } - } - - return face; + for(FontProviderTable::iterator i = instance->font_provider_table.begin(); i != instance->font_provider_table.end(); ++i) + { + if(*i == provider) + { + instance->font_provider_table.erase(i); + return; + } + } } } diff --git a/Source/Core/FontFamily.cpp b/Source/Core/FontFamily.cpp index 240e5263c..706498a81 100644 --- a/Source/Core/FontFamily.cpp +++ b/Source/Core/FontFamily.cpp @@ -26,7 +26,7 @@ */ #include "precompiled.h" -#include "FontFamily.h" +#include "../../Include/Rocket/Core/FontFamily.h" #include "FontFace.h" namespace Rocket { @@ -43,9 +43,9 @@ FontFamily::~FontFamily() } // Adds a new face to the family. -bool FontFamily::AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream) +bool FontFamily::AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream) { - FontFace* face = new FontFace(ft_face, style, weight, release_stream); + FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream); font_faces.push_back(face); return true; diff --git a/Source/Core/FontProvider.cpp b/Source/Core/FontProvider.cpp new file mode 100644 index 000000000..1f2503925 --- /dev/null +++ b/Source/Core/FontProvider.cpp @@ -0,0 +1,50 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include +#include + +namespace Rocket { +namespace Core { + +FontFamily* FontProvider::GetFontFamily(const String& family) +{ + FontFamily* font_family = NULL; + FontFamilyMap::iterator iterator = font_families.find(family); + if (iterator != font_families.end()) + font_family = (*iterator).second; + else + { + font_family = new FontFamily(family); + font_families[family] = font_family; + } + + return font_family; +} + +} +} diff --git a/Source/Core/FreeType/FontFace.cpp b/Source/Core/FreeType/FontFace.cpp new file mode 100644 index 000000000..d66c3afdf --- /dev/null +++ b/Source/Core/FreeType/FontFace.cpp @@ -0,0 +1,160 @@ +///* +// * This source file is part of libRocket, the HTML/CSS Interface Middleware +// * +// * For the latest information, see http://www.librocket.com +// * +// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy +// * of this software and associated documentation files (the "Software"), to deal +// * in the Software without restriction, including without limitation the rights +// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// * copies of the Software, and to permit persons to whom the Software is +// * furnished to do so, subject to the following conditions: +// * +// * The above copyright notice and this permission notice shall be included in +// * all copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// * THE SOFTWARE. +// * +// */ + +//#include "../precompiled.h" +//#include "FontFace.h" +//#include "FontFaceHandle.h" +//#include "../../Include/Rocket/Core/Log.h" + +//namespace Rocket { +//namespace Core { + +//FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream) +//{ +// face = _face; +// style = _style; +// weight = _weight; + +// release_stream = _release_stream; +//} + +//FontFace::~FontFace() +//{ +// for (HandleMap::iterator iterator = handles.begin(); iterator != handles.end(); ++iterator) +// { +// HandleList& handle_list = (*iterator).second; +// for (size_t i = 0; i < handle_list.size(); ++i) +// handle_list[i]->RemoveReference(); +// } + +// ReleaseFace(); +//} + +//// Returns the style of the font face. +//Font::Style FontFace::GetStyle() const +//{ +// return style; +//} + +//// Returns the weight of the font face. +//Font::Weight FontFace::GetWeight() const +//{ +// return weight; +//} + +//// Returns a handle for positioning and rendering this face at the given size. +//FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size) +//{ +// UnicodeRangeList charset; + +// HandleMap::iterator iterator = handles.find(size); +// if (iterator != handles.end()) +// { +// const HandleList& handles = (*iterator).second; + +// // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same +// // string). +// String raw_charset(_raw_charset); +// for (size_t i = 0; i < handles.size(); ++i) +// { +// if (handles[i]->GetRawCharset() == _raw_charset) +// { +// handles[i]->AddReference(); +// return handles[i]; +// } +// } + +// // Check all the handles if their charsets contain the requested charset. +// if (!UnicodeRange::BuildList(charset, raw_charset)) +// { +// Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); +// return NULL; +// } + +// for (size_t i = 0; i < handles.size(); ++i) +// { +// bool range_contained = true; + +// const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); +// for (size_t j = 0; j < charset.size() && range_contained; ++j) +// { +// if (!charset[j].IsContained(handle_charset)) +// range_contained = false; +// } + +// if (range_contained) +// { +// handles[i]->AddReference(); +// return handles[i]; +// } +// } +// } + +// // See if this face has been released. +// if (face == NULL) +// { +// Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); +// return NULL; +// } + +// // Construct and initialise the new handle. +// FontFaceHandle* handle = new FontFaceHandle(); +// if (!handle->Initialise(face, _raw_charset, size)) +// { +// handle->RemoveReference(); +// return NULL; +// } + +// // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face +// // releases it. +// if (iterator != handles.end()) +// (*iterator).second.push_back(handle); +// else +// handles[size] = HandleList(1, handle); + +// handle->AddReference(); + +// return handle; +//} + +//// Releases the face's FreeType face structure. +//void FontFace::ReleaseFace() +//{ +// if (face != NULL) +// { +// FT_Byte* face_memory = face->stream->base; +// FT_Done_Face(face); + +// if (release_stream) +// delete[] face_memory; + +// face = NULL; +// } +//} + +//} +//} diff --git a/Source/Core/FreeType/FontFace.h b/Source/Core/FreeType/FontFace.h new file mode 100644 index 000000000..64536b649 --- /dev/null +++ b/Source/Core/FreeType/FontFace.h @@ -0,0 +1,82 @@ +///* +// * This source file is part of libRocket, the HTML/CSS Interface Middleware +// * +// * For the latest information, see http://www.librocket.com +// * +// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy +// * of this software and associated documentation files (the "Software"), to deal +// * in the Software without restriction, including without limitation the rights +// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// * copies of the Software, and to permit persons to whom the Software is +// * furnished to do so, subject to the following conditions: +// * +// * The above copyright notice and this permission notice shall be included in +// * all copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// * THE SOFTWARE. +// * +// */ + +//#ifndef ROCKETCOREFONTFACE_H +//#define ROCKETCOREFONTFACE_H + +//#include "../../../Include/Rocket/Core/Font.h" +//#include +//#include FT_FREETYPE_H + +//namespace Rocket { +//namespace Core { + +//class FontFaceHandle; + +///** +// @author Peter Curry +// */ + +//class FontFace +//{ +//public: +// FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream); +// ~FontFace(); + +// /// Returns the style of the font face. +// /// @return The font face's style. +// Font::Style GetStyle() const; +// /// Returns the weight of the font face. +// /// @return The font face's weight. +// Font::Weight GetWeight() const; + +// /// Returns a handle for positioning and rendering this face at the given size. +// /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. +// /// @param[in] size The size of the desired handle, in points. +// /// @return The shared font handle. +// FontFaceHandle* GetHandle(const String& charset, int size); + +// /// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed, +// /// but existing ones can still be fetched. +// void ReleaseFace(); + +//private: +// FT_Face face; +// Font::Style style; +// Font::Weight weight; + +// bool release_stream; + +// typedef std::vector< FontFaceHandle* > HandleList; +// typedef std::map< int, HandleList > HandleMap; +// HandleMap handles; +//}; + +//} +//} + +//#endif diff --git a/Source/Core/FreeType/FontFaceHandle.cpp b/Source/Core/FreeType/FontFaceHandle.cpp new file mode 100644 index 000000000..6f1b4c8a1 --- /dev/null +++ b/Source/Core/FreeType/FontFaceHandle.cpp @@ -0,0 +1,566 @@ +///* +// * This source file is part of libRocket, the HTML/CSS Interface Middleware +// * +// * For the latest information, see http://www.librocket.com +// * +// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy +// * of this software and associated documentation files (the "Software"), to deal +// * in the Software without restriction, including without limitation the rights +// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// * copies of the Software, and to permit persons to whom the Software is +// * furnished to do so, subject to the following conditions: +// * +// * The above copyright notice and this permission notice shall be included in +// * all copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// * THE SOFTWARE. +// * +// */ + +//#include "precompiled.h" +//#include "FontFaceHandle.h" +//#include +//#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; +//} + +//} +//} diff --git a/Source/Core/FreeType/FontFaceHandle.h b/Source/Core/FreeType/FontFaceHandle.h new file mode 100644 index 000000000..7f75d8f5b --- /dev/null +++ b/Source/Core/FreeType/FontFaceHandle.h @@ -0,0 +1,182 @@ +///* +// * This source file is part of libRocket, the HTML/CSS Interface Middleware +// * +// * For the latest information, see http://www.librocket.com +// * +// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy +// * of this software and associated documentation files (the "Software"), to deal +// * in the Software without restriction, including without limitation the rights +// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// * copies of the Software, and to permit persons to whom the Software is +// * furnished to do so, subject to the following conditions: +// * +// * The above copyright notice and this permission notice shall be included in +// * all copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// * THE SOFTWARE. +// * +// */ + +//#ifndef ROCKETCOREFONTFACEHANDLE_H +//#define ROCKETCOREFONTFACEHANDLE_H + +//#include "../../Include/Rocket/Core/ReferenceCountable.h" +//#include "UnicodeRange.h" +//#include "../../Include/Rocket/Core/Font.h" +//#include "../../Include/Rocket/Core/FontEffect.h" +//#include "../../Include/Rocket/Core/FontGlyph.h" +//#include "../../Include/Rocket/Core/Geometry.h" +//#include "../../Include/Rocket/Core/String.h" +//#include "../../Include/Rocket/Core/Texture.h" +//#include +//#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 diff --git a/Source/Core/FreeType/FontFaceLayer.cpp b/Source/Core/FreeType/FontFaceLayer.cpp new file mode 100644 index 000000000..504da0483 --- /dev/null +++ b/Source/Core/FreeType/FontFaceLayer.cpp @@ -0,0 +1,242 @@ +///* +// * This source file is part of libRocket, the HTML/CSS Interface Middleware +// * +// * For the latest information, see http://www.librocket.com +// * +// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy +// * of this software and associated documentation files (the "Software"), to deal +// * in the Software without restriction, including without limitation the rights +// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// * copies of the Software, and to permit persons to whom the Software is +// * furnished to do so, subject to the following conditions: +// * +// * The above copyright notice and this permission notice shall be included in +// * all copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// * THE SOFTWARE. +// * +// */ + +//#include "precompiled.h" +//#include "FontFaceLayer.h" +//#include "../../Include/Rocket/Core/Core.h" +//#include "FontFaceHandle.h" + +//namespace Rocket { +//namespace Core { + +//FontFaceLayer::FontFaceLayer() : colour(255, 255, 255) +//{ +// handle = NULL; +// effect = NULL; +//} + +//FontFaceLayer::~FontFaceLayer() +//{ +// if (effect != NULL) +// effect->RemoveReference(); +//} + +//// Generates the character and texture data for the layer. +//bool FontFaceLayer::Initialise(const FontFaceHandle* _handle, FontEffect* _effect, const FontFaceLayer* clone, bool deep_clone) +//{ +// handle = _handle; +// effect = _effect; +// if (effect != NULL) +// { +// effect->AddReference(); +// colour = effect->GetColour(); +// } + +// const FontGlyphList& glyphs = handle->GetGlyphs(); + +// // Clone the geometry and textures from the clone layer. +// if (clone != NULL) +// { +// // Copy the cloned layer's characters. +// characters = clone->characters; + +// // Copy (and reference) the cloned layer's textures. +// for (size_t i = 0; i < clone->textures.size(); ++i) +// textures.push_back(clone->textures[i]); + +// // Request the effect (if we have one) adjust the origins as appropriate. +// if (!deep_clone && +// effect != NULL) +// { +// for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) +// { +// const FontGlyph& glyph = *i; + +// if (glyph.character >= characters.size()) +// continue; + +// Character& character = characters[glyph.character]; + +// Vector2i glyph_origin(Math::RealToInteger(character.origin.x), Math::RealToInteger(character.origin.y)); +// Vector2i glyph_dimensions(Math::RealToInteger(character.dimensions.x), Math::RealToInteger(character.dimensions.y)); + +// if (effect->GetGlyphMetrics(glyph_origin, glyph_dimensions, glyph)) +// { +// character.origin.x = (float) glyph_origin.x; +// character.origin.y = (float) glyph_origin.y; +// } +// else +// character.texture_index = -1; +// } +// } +// } +// else +// { +// // Initialise the texture layout for the glyphs. +// characters.resize(glyphs.size(), Character()); +// for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) +// { +// const FontGlyph& glyph = *i; + +// Vector2i glyph_origin(0, 0); +// Vector2i glyph_dimensions = glyph.bitmap_dimensions; + +// // Adjust glyph origin / dimensions for the font effect. +// if (effect != NULL) +// { +// if (!effect->GetGlyphMetrics(glyph_origin, glyph_dimensions, glyph)) +// continue; +// } + +// Character character; +// character.origin = Vector2f((float) (glyph_origin.x + glyph.bearing.x), (float) (glyph_origin.y - glyph.bearing.y)); +// character.dimensions = Vector2f((float) glyph_dimensions.x - glyph_origin.x, (float) glyph_dimensions.y - glyph_origin.y); +// characters[glyph.character] = character; + +// // Add the character's dimensions into the texture layout engine. +// texture_layout.AddRectangle(glyph.character, glyph_dimensions - glyph_origin); +// } + +// // Generate the texture layout; this will position the glyph rectangles efficiently and +// // allocate the texture data ready for writing. +// if (!texture_layout.GenerateLayout(512)) +// return false; + + +// // Iterate over each rectangle in the layout, copying the glyph data into the rectangle as +// // appropriate and generating geometry. +// for (int i = 0; i < texture_layout.GetNumRectangles(); ++i) +// { +// TextureLayoutRectangle& rectangle = texture_layout.GetRectangle(i); +// const TextureLayoutTexture& texture = texture_layout.GetTexture(rectangle.GetTextureIndex()); +// Character& character = characters[(word) rectangle.GetId()]; + +// // Set the character's texture index. +// character.texture_index = rectangle.GetTextureIndex(); + +// // Generate the character's texture coordinates. +// character.texcoords[0].x = float(rectangle.GetPosition().x) / float(texture.GetDimensions().x); +// character.texcoords[0].y = float(rectangle.GetPosition().y) / float(texture.GetDimensions().y); +// character.texcoords[1].x = float(rectangle.GetPosition().x + rectangle.GetDimensions().x) / float(texture.GetDimensions().x); +// character.texcoords[1].y = float(rectangle.GetPosition().y + rectangle.GetDimensions().y) / float(texture.GetDimensions().y); +// } + + +// // Generate the textures. +// for (int i = 0; i < texture_layout.GetNumTextures(); ++i) +// { +// Texture texture; +// if (!texture.Load(String(64, "?font::%p/%p/%d", handle, effect, i))) +// return false; + +// textures.push_back(texture); +// } +// } + + +// return true; +//} + +//// Generates the texture data for a layer (for the texture database). +//bool FontFaceLayer::GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id) +//{ +// if (texture_id < 0 || +// texture_id > texture_layout.GetNumTextures()) +// return false; + +// const FontGlyphList& glyphs = handle->GetGlyphs(); + +// // Generate the texture data. +// texture_data = texture_layout.GetTexture(texture_id).AllocateTexture(); +// texture_dimensions = texture_layout.GetTexture(texture_id).GetDimensions(); + +// for (int i = 0; i < texture_layout.GetNumRectangles(); ++i) +// { +// TextureLayoutRectangle& rectangle = texture_layout.GetRectangle(i); +// Character& character = characters[(word) rectangle.GetId()]; + +// if (character.texture_index != texture_id) +// continue; + +// const FontGlyph& glyph = glyphs[rectangle.GetId()]; + +// if (effect == NULL) +// { +// // Copy the glyph's bitmap data into its allocated texture. +// if (glyph.bitmap_data != NULL) +// { +// byte* destination = rectangle.GetTextureData(); +// byte* source = glyph.bitmap_data; + +// for (int j = 0; j < glyph.bitmap_dimensions.y; ++j) +// { +// for (int k = 0; k < glyph.bitmap_dimensions.x; ++k) +// destination[k * 4 + 3] = source[k]; + +// destination += rectangle.GetTextureStride(); +// source += glyph.bitmap_dimensions.x; +// } +// } +// } +// else +// { +// effect->GenerateGlyphTexture(rectangle.GetTextureData(), Vector2i(Math::RealToInteger(character.dimensions.x), Math::RealToInteger(character.dimensions.y)), rectangle.GetTextureStride(), glyph); +// } +// } + +// return true; +//} + +//// Returns the effect used to generate the layer. +//const FontEffect* FontFaceLayer::GetFontEffect() const +//{ +// return effect; +//} + +//// Returns on the layer's textures. +//const Texture* FontFaceLayer::GetTexture(int index) +//{ +// ROCKET_ASSERT(index >= 0); +// ROCKET_ASSERT(index < GetNumTextures()); + +// return &(textures[index]); +//} + +//// Returns the number of textures employed by this layer. +//int FontFaceLayer::GetNumTextures() const +//{ +// return (int) textures.size(); +//} + +//// Returns the layer's colour. +//const Colourb& FontFaceLayer::GetColour() const +//{ +// return colour; +//} + +//} +//} diff --git a/Source/Core/FreeType/FontFaceLayer.h b/Source/Core/FreeType/FontFaceLayer.h new file mode 100644 index 000000000..600db258b --- /dev/null +++ b/Source/Core/FreeType/FontFaceLayer.h @@ -0,0 +1,142 @@ +///* +// * This source file is part of libRocket, the HTML/CSS Interface Middleware +// * +// * For the latest information, see http://www.librocket.com +// * +// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy +// * of this software and associated documentation files (the "Software"), to deal +// * in the Software without restriction, including without limitation the rights +// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// * copies of the Software, and to permit persons to whom the Software is +// * furnished to do so, subject to the following conditions: +// * +// * The above copyright notice and this permission notice shall be included in +// * all copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// * THE SOFTWARE. +// * +// */ + +//#ifndef ROCKETCOREFONTFACELAYER_H +//#define ROCKETCOREFONTFACELAYER_H + +//#include "../../Include/Rocket/Core/FontGlyph.h" +//#include "../../Include/Rocket/Core/Geometry.h" +//#include "../../Include/Rocket/Core/GeometryUtilities.h" +//#include "../../Include/Rocket/Core/String.h" +//#include "../../Include/Rocket/Core/Texture.h" +//#include "TextureLayout.h" + +//namespace Rocket { +//namespace Core { + +//class FontEffect; +//class FontFaceHandle; + +///** +// A textured layer stored as part of a font face handle. Each handle will have at least a base +// layer for the standard font. Further layers can be added to allow to rendering of text effects. + +// @author Peter Curry +// */ + +//class FontFaceLayer +//{ +//public: +// FontFaceLayer(); +// ~FontFaceLayer(); + +// /// Generates the character and texture data for the layer. +// /// @param[in] handle The handle generating this layer. +// /// @param[in] effect The effect to initialise the layer with. +// /// @param[in] clone The layer to optionally clone geometry and texture data from. +// /// @param[in] deep_clone If true, the clones geometry will be completely cloned and the effect will have no option to affect even the glyph origins. +// /// @return True if the layer was generated successfully, false if not. +// bool Initialise(const FontFaceHandle* handle, FontEffect* effect = NULL, const FontFaceLayer* clone = NULL, bool deep_clone = false); + +// /// Generates the texture data for a layer (for the texture database). +// /// @param[out] texture_data The pointer to be set to the generated texture data. +// /// @param[out] texture_dimensions The dimensions of the texture. +// /// @param[in] glyphs The glyphs required by the font face handle. +// /// @param[in] texture_id The index of the texture within the layer to generate. +// bool GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id); +// /// Generates the geometry required to render a single character. +// /// @param[out] geometry An array of geometries this layer will write to. It must be at least as big as the number of textures in this layer. +// /// @param[in] character_code The character to generate geometry for. +// /// @param[in] position The position of the baseline. +// /// @param[in] colour The colour of the string. +// inline void GenerateGeometry(Geometry* geometry, const word character_code, const Vector2f& position, const Colourb& colour) const +// { +// if (character_code >= characters.size()) +// return; + +// const Character& character = characters[character_code]; +// if (character.texture_index < 0) +// return; + +// // Generate the geometry for the character. +// std::vector< Vertex >& character_vertices = geometry[character.texture_index].GetVertices(); +// std::vector< int >& character_indices = geometry[character.texture_index].GetIndices(); + +// character_vertices.resize(character_vertices.size() + 4); +// character_indices.resize(character_indices.size() + 6); +// GeometryUtilities::GenerateQuad(&character_vertices[0] + (character_vertices.size() - 4), &character_indices[0] + (character_indices.size() - 6), Vector2f(position.x + character.origin.x, position.y + character.origin.y), character.dimensions, colour, character.texcoords[0], character.texcoords[1], (int)character_vertices.size() - 4); +// } + +// /// Returns the effect used to generate the layer. +// /// @return The layer's effect. +// const FontEffect* GetFontEffect() const; + +// /// Returns on the layer's textures. +// /// @param[in] index The index of the desired texture. +// /// @return The requested texture. +// const Texture* GetTexture(int index); +// /// Returns the number of textures employed by this layer. +// /// @return The number of used textures. +// int GetNumTextures() const; + +// /// Returns the layer's colour. +// /// @return The layer's colour. +// const Colourb& GetColour() const; + +//private: +// struct Character +// { +// Character() : texture_index(-1) { } + +// // The offset, in pixels, of the baseline from the start of this character's geometry. +// Vector2f origin; +// // The width and height, in pixels, of this character's geometry. +// Vector2f dimensions; +// // The texture coordinates for the character's geometry. +// Vector2f texcoords[2]; + +// // The texture this character renders from. +// int texture_index; +// }; + +// typedef std::vector< Character > CharacterList; +// typedef std::vector< Texture > TextureList; + +// const FontFaceHandle* handle; +// FontEffect* effect; + +// TextureLayout texture_layout; + +// CharacterList characters; +// TextureList textures; +// Colourb colour; +//}; + +//} +//} + +//#endif diff --git a/Source/Core/FreeType/FontFamily.cpp b/Source/Core/FreeType/FontFamily.cpp new file mode 100644 index 000000000..0cd4349e0 --- /dev/null +++ b/Source/Core/FreeType/FontFamily.cpp @@ -0,0 +1,79 @@ +///* +// * This source file is part of libRocket, the HTML/CSS Interface Middleware +// * +// * For the latest information, see http://www.librocket.com +// * +// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy +// * of this software and associated documentation files (the "Software"), to deal +// * in the Software without restriction, including without limitation the rights +// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// * copies of the Software, and to permit persons to whom the Software is +// * furnished to do so, subject to the following conditions: +// * +// * The above copyright notice and this permission notice shall be included in +// * all copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// * THE SOFTWARE. +// * +// */ + +//#include "precompiled.h" +//#include "FontFamily.h" +//#include "FontFace.h" + +//namespace Rocket { +//namespace Core { + +//FontFamily::FontFamily(const String& name) : name(name) +//{ +//} + +//FontFamily::~FontFamily() +//{ +// for (size_t i = 0; i < font_faces.size(); ++i) +// delete font_faces[i]; +//} + +//// Adds a new face to the family. +//bool FontFamily::AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream) +//{ +// FontFace* face = new FontFace(ft_face, style, weight, release_stream); +// font_faces.push_back(face); + +// return true; +//} + +//// Returns a handle to the most appropriate font in the family, at the correct size. +//FontFaceHandle* FontFamily::GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size) +//{ +// // Search for a face of the same style, and match the weight as closely as we can. +// FontFace* matching_face = NULL; +// for (size_t i = 0; i < font_faces.size(); i++) +// { +// // If we've found a face matching the style, then ... great! We'll match it regardless of the weight. However, +// // if it's a perfect match, then we'll stop looking altogether. +// if (font_faces[i]->GetStyle() == style) +// { +// matching_face = font_faces[i]; + +// if (font_faces[i]->GetWeight() == weight) +// break; +// } +// } + +// if (matching_face == NULL) +// return NULL; + +// return matching_face->GetHandle(charset, size); +//} + +//} +//} diff --git a/Source/Core/FreeType/FontFamily.h b/Source/Core/FreeType/FontFamily.h new file mode 100644 index 000000000..58d9025d9 --- /dev/null +++ b/Source/Core/FreeType/FontFamily.h @@ -0,0 +1,81 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef ROCKETCOREFREETYPEFONTFAMILY_H +#define ROCKETCOREFREETYPEFONTFAMILY_H + +#include +#include +#include +#include FT_FREETYPE_H + +namespace Rocket { +namespace Core { + +class FontFace; +class FontFaceHandle; + +/** + @author Peter Curry + */ + +namespace FreeType { + +class FontFamily : public Rocket::Core::FontFamily +{ +public: + FontFamily(const String& name); + ~FontFamily(); + + /// Adds a new face to the family. + /// @param[in] ft_face The previously loaded FreeType face. + /// @param[in] style The style of the new face. + /// @param[in] weight The weight of the new face. + /// @param[in] release_stream True if the application must free the face's memory stream. + /// @return True if the face was loaded successfully, false otherwise. + bool AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream); + + /// Returns a handle to the most appropriate font in the family, at the correct size. + /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. + /// @param[in] style The style of the desired handle. + /// @param[in] weight The weight of the desired handle. + /// @param[in] size The size of desired handle, in points. + /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise. + FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size); + +private: + String name; + + typedef std::vector< FontFace* > FontFaceList; + FontFaceList font_faces; +}; + +} +} +} + +#endif diff --git a/Source/Core/FreeType/FontProvider.cpp b/Source/Core/FreeType/FontProvider.cpp new file mode 100644 index 000000000..774985a2f --- /dev/null +++ b/Source/Core/FreeType/FontProvider.cpp @@ -0,0 +1,267 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "../precompiled.h" +#include +#include "FontFaceHandle.h" +#include +#include "FontFamily.h" +#include +#include +#include FT_FREETYPE_H + +namespace Rocket { +namespace Core { +namespace FreeType { + +FontProvider* FontProvider::instance = NULL; + +static FT_Library ft_library = NULL; + +FontProvider::FontProvider() +{ + ROCKET_ASSERT(instance == NULL); + instance = this; +} + +FontProvider::~FontProvider() +{ + ROCKET_ASSERT(instance == this); + instance = NULL; +} + +bool FontProvider::Initialise() +{ + if (instance == NULL) + { + new FontProvider(); + + FT_Error result = FT_Init_FreeType(&ft_library); + if (result != 0) + { + Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result); + Shutdown(); + return false; + } + } + + return true; +} + +void FontProvider::Shutdown() +{ + if (instance != NULL) + { + for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i) + delete (*i).second; + + if (ft_library != NULL) + { + FT_Done_FreeType(ft_library); + ft_library = NULL; + } + + delete instance; + } +} + +// Loads a new font face. +bool FontProvider::LoadFontFace(const String& file_name) +{ + FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); + return false; + } + + Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; + Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; + + if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return false; + } +} + +// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself. +bool FontProvider::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight) +{ + FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); + return false; + } + + if (instance->AddFace(ft_face, family, style, weight, true)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return false; + } +} + +// Adds a new font face to the database, loading from memory. +bool FontProvider::LoadFontFace(const byte* data, int data_length) +{ + FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); + return false; + } + + Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; + Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; + + if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return false; + } +} + +// Adds a new font face to the database, loading from memory, ignoring any family, style and weight information stored in the face itself. +bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight) +{ + FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); + return false; + } + + if (instance->AddFace(ft_face, family, style, weight, false)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return false; + } +} + +// Returns a handle to a font face that can be used to position and render text. +Rocket::Core::FontFaceHandle* FontProvider::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) +{ + FontFamilyMap::iterator iterator = instance->font_families.find(family); + if (iterator == instance->font_families.end()) + return NULL; + + return (*iterator).second->GetFaceHandle(charset, style, weight, size); +} + + +// Adds a loaded face to the appropriate font family. +bool FontProvider::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream) +{ + Rocket::Core::FontFamily* font_family = NULL; + FontFamilyMap::iterator iterator = instance->font_families.find(family); + if (iterator != instance->font_families.end()) + font_family = (*iterator).second; + else + { + font_family = new FontFamily(family); + instance->font_families[family] = font_family; + } + + return font_family->AddFace((FT_Face) face, style, weight, release_stream); +} + +// Loads a FreeType face. +void* FontProvider::LoadFace(const String& file_name) +{ + FileInterface* file_interface = GetFileInterface(); + FileHandle handle = file_interface->Open(file_name); + + if (!handle) + { + return NULL; + } + + size_t length = file_interface->Length(handle); + + FT_Byte* buffer = new FT_Byte[length]; + file_interface->Read(buffer, length, handle); + file_interface->Close(handle); + + return LoadFace(buffer, (int)length, file_name, true); +} + +// Loads a FreeType face from memory. +void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data) +{ + FT_Face face = NULL; + int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face); + if (error != 0) + { + Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString()); + if (local_data) + delete[] data; + + return NULL; + } + + // Initialise the character mapping on the face. + if (face->charmap == NULL) + { + FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); + if (face->charmap == NULL) + { + Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString()); + FT_Done_Face(face); + if (local_data) + delete[] data; + + return NULL; + } + } + + return face; +} + +} +} +} diff --git a/Source/Debugger/Plugin.cpp b/Source/Debugger/Plugin.cpp index 285c2d4a2..6184d4c5a 100644 --- a/Source/Debugger/Plugin.cpp +++ b/Source/Debugger/Plugin.cpp @@ -286,8 +286,8 @@ Plugin* Plugin::GetInstance() bool Plugin::LoadFont() { - return (Core::FontDatabase::LoadFontFace(lacuna_regular, sizeof(lacuna_regular) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_NORMAL, Core::Font::WEIGHT_NORMAL) && - Core::FontDatabase::LoadFontFace(lacuna_italic, sizeof(lacuna_italic) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_ITALIC, Core::Font::WEIGHT_NORMAL)); + return (Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_regular, sizeof(lacuna_regular) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_NORMAL, Core::Font::WEIGHT_NORMAL) && + Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_italic, sizeof(lacuna_italic) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_ITALIC, Core::Font::WEIGHT_NORMAL)); } bool Plugin::LoadMenuElement() From 61443dacb249d6e0f0a4ab6f53d2f7073aa0ed71 Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Sat, 29 Aug 2015 12:09:25 +0200 Subject: [PATCH 02/13] FontFace --- Build/cmake/FileList.cmake | 2 +- {Source => Include/Rocket}/Core/FontFace.h | 15 +- Include/Rocket/Core/FontFamily.h | 8 +- Include/Rocket/Core/FontProvider.h | 4 +- Include/Rocket/Core/FreeType/FontProvider.h | 11 - Source/Core/FontDatabase.cpp | 3 + Source/Core/FontFace.cpp | 97 +------ Source/Core/FontFamily.cpp | 11 +- Source/Core/FontProvider.cpp | 15 +- Source/Core/FreeType/FontFace.cpp | 299 +++++++++----------- Source/Core/FreeType/FontFace.h | 129 ++++----- Source/Core/FreeType/FontFamily.cpp | 137 ++++----- Source/Core/FreeType/FontFamily.h | 16 +- Source/Core/FreeType/FontProvider.cpp | 21 +- 14 files changed, 284 insertions(+), 484 deletions(-) rename {Source => Include/Rocket}/Core/FontFace.h (88%) diff --git a/Build/cmake/FileList.cmake b/Build/cmake/FileList.cmake index 8bf5df20d..37d2008c5 100644 --- a/Build/cmake/FileList.cmake +++ b/Build/cmake/FileList.cmake @@ -36,7 +36,6 @@ set(Core_HDR_FILES ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectOutlineInstancer.h ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectShadow.h ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectShadowInstancer.h - ${PROJECT_SOURCE_DIR}/Source/Core/FontFace.h ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceHandle.h ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.h ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.h @@ -131,6 +130,7 @@ set(Core_PUB_HDR_FILES ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontDatabase.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffect.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffectInstancer.h + ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontFace.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontFamily.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontGlyph.h ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontProvider.h diff --git a/Source/Core/FontFace.h b/Include/Rocket/Core/FontFace.h similarity index 88% rename from Source/Core/FontFace.h rename to Include/Rocket/Core/FontFace.h index a428d0d7e..28b2ff566 100644 --- a/Source/Core/FontFace.h +++ b/Include/Rocket/Core/FontFace.h @@ -28,9 +28,7 @@ #ifndef ROCKETCOREFONTFACE_H #define ROCKETCOREFONTFACE_H -#include "../../Include/Rocket/Core/Font.h" -#include -#include FT_FREETYPE_H +#include "Font.h" namespace Rocket { namespace Core { @@ -44,8 +42,8 @@ class FontFaceHandle; class FontFace { public: - FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream); - ~FontFace(); + FontFace(Font::Style style, Font::Weight weight, bool release_stream); + virtual ~FontFace(); /// Returns the style of the font face. /// @return The font face's style. @@ -58,14 +56,13 @@ class FontFace /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. /// @param[in] size The size of the desired handle, in points. /// @return The shared font handle. - FontFaceHandle* GetHandle(const String& charset, int size); + virtual FontFaceHandle* GetHandle(const String& charset, int size) = 0; /// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed, /// but existing ones can still be fetched. - void ReleaseFace(); + virtual void ReleaseFace() = 0; -private: - FT_Face face; +protected: Font::Style style; Font::Weight weight; diff --git a/Include/Rocket/Core/FontFamily.h b/Include/Rocket/Core/FontFamily.h index fe9234a40..a65aa1905 100644 --- a/Include/Rocket/Core/FontFamily.h +++ b/Include/Rocket/Core/FontFamily.h @@ -46,7 +46,7 @@ class FontFamily { public: FontFamily(const String& name); - ~FontFamily(); + virtual ~FontFamily(); /// Adds a new face to the family. /// @param[in] ft_face The previously loaded FreeType face. @@ -54,7 +54,7 @@ class FontFamily /// @param[in] weight The weight of the new face. /// @param[in] release_stream True if the application must free the face's memory stream. /// @return True if the face was loaded successfully, false otherwise. - bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream); + virtual bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream) = 0; /// Returns a handle to the most appropriate font in the family, at the correct size. /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. @@ -62,9 +62,9 @@ class FontFamily /// @param[in] weight The weight of the desired handle. /// @param[in] size The size of desired handle, in points. /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise. - FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size); + FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size); -private: +protected: String name; typedef std::vector< FontFace* > FontFaceList; diff --git a/Include/Rocket/Core/FontProvider.h b/Include/Rocket/Core/FontProvider.h index ec162c4c9..2c8018f43 100644 --- a/Include/Rocket/Core/FontProvider.h +++ b/Include/Rocket/Core/FontProvider.h @@ -56,12 +56,10 @@ class ROCKETCORE_API FontProvider /// @param[in] weight The weight of the desired font handle. /// @param[in] size The size of desired handle, in points. /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise. - virtual FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) = 0; + FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size); protected: - FontFamily* GetFontFamily(const String& family); - typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap; FontFamilyMap font_families; }; diff --git a/Include/Rocket/Core/FreeType/FontProvider.h b/Include/Rocket/Core/FreeType/FontProvider.h index c684bf63f..e9c034e00 100644 --- a/Include/Rocket/Core/FreeType/FontProvider.h +++ b/Include/Rocket/Core/FreeType/FontProvider.h @@ -80,17 +80,6 @@ class ROCKETCORE_API FontProvider : public Rocket::Core::FontProvider /// @return True if the face was loaded successfully, false otherwise. static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight); - /// Returns a handle to a font face that can be used to position and render text. This will return the closest match - /// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a - /// valid handle. - /// @param[in] family The family of the desired font handle. - /// @param[in] charset The set of characters required in the font face, as a comma-separated list of unicode ranges. - /// @param[in] style The style of the desired font handle. - /// @param[in] weight The weight of the desired font handle. - /// @param[in] size The size of desired handle, in points. - /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise. - virtual FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size); - private: FontProvider(void); ~FontProvider(void); diff --git a/Source/Core/FontDatabase.cpp b/Source/Core/FontDatabase.cpp index bf8aae7d5..0d71bf700 100644 --- a/Source/Core/FontDatabase.cpp +++ b/Source/Core/FontDatabase.cpp @@ -37,6 +37,7 @@ namespace Rocket { namespace Core { FontDatabase* FontDatabase::instance = NULL; +FontDatabase::FontProviderTable FontDatabase::font_provider_table; typedef std::map< String, FontEffect* > FontEffectCache; FontEffectCache font_effect_cache; @@ -113,6 +114,8 @@ 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; diff --git a/Source/Core/FontFace.cpp b/Source/Core/FontFace.cpp index 9ed4c2460..7f8a3f4ca 100644 --- a/Source/Core/FontFace.cpp +++ b/Source/Core/FontFace.cpp @@ -26,16 +26,15 @@ */ #include "precompiled.h" -#include "FontFace.h" +#include "../../Include/Rocket/Core/FontFace.h" #include "FontFaceHandle.h" #include "../../Include/Rocket/Core/Log.h" namespace Rocket { namespace Core { -FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream) +FontFace::FontFace(Font::Style _style, Font::Weight _weight, bool _release_stream) { - face = _face; style = _style; weight = _weight; @@ -50,8 +49,6 @@ FontFace::~FontFace() for (size_t i = 0; i < handle_list.size(); ++i) handle_list[i]->RemoveReference(); } - - ReleaseFace(); } // Returns the style of the font face. @@ -66,95 +63,5 @@ Font::Weight FontFace::GetWeight() const return weight; } -// Returns a handle for positioning and rendering this face at the given size. -FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size) -{ - UnicodeRangeList charset; - - HandleMap::iterator iterator = handles.find(size); - if (iterator != handles.end()) - { - const HandleList& handles = (*iterator).second; - - // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same - // string). - String raw_charset(_raw_charset); - for (size_t i = 0; i < handles.size(); ++i) - { - if (handles[i]->GetRawCharset() == _raw_charset) - { - handles[i]->AddReference(); - return handles[i]; - } - } - - // Check all the handles if their charsets contain the requested charset. - if (!UnicodeRange::BuildList(charset, raw_charset)) - { - Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); - return NULL; - } - - for (size_t i = 0; i < handles.size(); ++i) - { - bool range_contained = true; - - const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); - for (size_t j = 0; j < charset.size() && range_contained; ++j) - { - if (!charset[j].IsContained(handle_charset)) - range_contained = false; - } - - if (range_contained) - { - handles[i]->AddReference(); - return handles[i]; - } - } - } - - // See if this face has been released. - if (face == NULL) - { - Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); - return NULL; - } - - // Construct and initialise the new handle. - FontFaceHandle* handle = new FontFaceHandle(); - if (!handle->Initialise(face, _raw_charset, size)) - { - handle->RemoveReference(); - return NULL; - } - - // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face - // releases it. - if (iterator != handles.end()) - (*iterator).second.push_back(handle); - else - handles[size] = HandleList(1, handle); - - handle->AddReference(); - - return handle; -} - -// Releases the face's FreeType face structure. -void FontFace::ReleaseFace() -{ - if (face != NULL) - { - FT_Byte* face_memory = face->stream->base; - FT_Done_Face(face); - - if (release_stream) - delete[] face_memory; - - face = NULL; - } -} - } } diff --git a/Source/Core/FontFamily.cpp b/Source/Core/FontFamily.cpp index 706498a81..e044e1c27 100644 --- a/Source/Core/FontFamily.cpp +++ b/Source/Core/FontFamily.cpp @@ -27,7 +27,7 @@ #include "precompiled.h" #include "../../Include/Rocket/Core/FontFamily.h" -#include "FontFace.h" +#include "../../Include/Rocket/Core/FontFace.h" namespace Rocket { namespace Core { @@ -42,15 +42,6 @@ FontFamily::~FontFamily() delete font_faces[i]; } -// Adds a new face to the family. -bool FontFamily::AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream) -{ - FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream); - font_faces.push_back(face); - - return true; -} - // Returns a handle to the most appropriate font in the family, at the correct size. FontFaceHandle* FontFamily::GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size) { diff --git a/Source/Core/FontProvider.cpp b/Source/Core/FontProvider.cpp index 1f2503925..99fffd145 100644 --- a/Source/Core/FontProvider.cpp +++ b/Source/Core/FontProvider.cpp @@ -31,19 +31,14 @@ namespace Rocket { namespace Core { -FontFamily* FontProvider::GetFontFamily(const String& family) +// Returns a handle to a font face that can be used to position and render text. +Rocket::Core::FontFaceHandle* FontProvider::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) { - FontFamily* font_family = NULL; FontFamilyMap::iterator iterator = font_families.find(family); - if (iterator != font_families.end()) - font_family = (*iterator).second; - else - { - font_family = new FontFamily(family); - font_families[family] = font_family; - } + if (iterator == font_families.end()) + return NULL; - return font_family; + return (*iterator).second->GetFaceHandle(charset, style, weight, size); } } diff --git a/Source/Core/FreeType/FontFace.cpp b/Source/Core/FreeType/FontFace.cpp index d66c3afdf..630e2df72 100644 --- a/Source/Core/FreeType/FontFace.cpp +++ b/Source/Core/FreeType/FontFace.cpp @@ -1,160 +1,139 @@ -///* -// * This source file is part of libRocket, the HTML/CSS Interface Middleware -// * -// * For the latest information, see http://www.librocket.com -// * -// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd -// * -// * Permission is hereby granted, free of charge, to any person obtaining a copy -// * of this software and associated documentation files (the "Software"), to deal -// * in the Software without restriction, including without limitation the rights -// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// * copies of the Software, and to permit persons to whom the Software is -// * furnished to do so, subject to the following conditions: -// * -// * The above copyright notice and this permission notice shall be included in -// * all copies or substantial portions of the Software. -// * -// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// * THE SOFTWARE. -// * -// */ - -//#include "../precompiled.h" -//#include "FontFace.h" -//#include "FontFaceHandle.h" -//#include "../../Include/Rocket/Core/Log.h" - -//namespace Rocket { -//namespace Core { - -//FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream) -//{ -// face = _face; -// style = _style; -// weight = _weight; - -// release_stream = _release_stream; -//} - -//FontFace::~FontFace() -//{ -// for (HandleMap::iterator iterator = handles.begin(); iterator != handles.end(); ++iterator) -// { -// HandleList& handle_list = (*iterator).second; -// for (size_t i = 0; i < handle_list.size(); ++i) -// handle_list[i]->RemoveReference(); -// } - -// ReleaseFace(); -//} - -//// Returns the style of the font face. -//Font::Style FontFace::GetStyle() const -//{ -// return style; -//} - -//// Returns the weight of the font face. -//Font::Weight FontFace::GetWeight() const -//{ -// return weight; -//} - -//// Returns a handle for positioning and rendering this face at the given size. -//FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size) -//{ -// UnicodeRangeList charset; - -// HandleMap::iterator iterator = handles.find(size); -// if (iterator != handles.end()) -// { -// const HandleList& handles = (*iterator).second; - -// // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same -// // string). -// String raw_charset(_raw_charset); -// for (size_t i = 0; i < handles.size(); ++i) -// { -// if (handles[i]->GetRawCharset() == _raw_charset) -// { -// handles[i]->AddReference(); -// return handles[i]; -// } -// } - -// // Check all the handles if their charsets contain the requested charset. -// if (!UnicodeRange::BuildList(charset, raw_charset)) -// { -// Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); -// return NULL; -// } - -// for (size_t i = 0; i < handles.size(); ++i) -// { -// bool range_contained = true; - -// const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); -// for (size_t j = 0; j < charset.size() && range_contained; ++j) -// { -// if (!charset[j].IsContained(handle_charset)) -// range_contained = false; -// } - -// if (range_contained) -// { -// handles[i]->AddReference(); -// return handles[i]; -// } -// } -// } - -// // See if this face has been released. -// if (face == NULL) -// { -// Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); -// return NULL; -// } - -// // Construct and initialise the new handle. -// FontFaceHandle* handle = new FontFaceHandle(); -// if (!handle->Initialise(face, _raw_charset, size)) -// { -// handle->RemoveReference(); -// return NULL; -// } - -// // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face -// // releases it. -// if (iterator != handles.end()) -// (*iterator).second.push_back(handle); -// else -// handles[size] = HandleList(1, handle); - -// handle->AddReference(); - -// return handle; -//} - -//// Releases the face's FreeType face structure. -//void FontFace::ReleaseFace() -//{ -// if (face != NULL) -// { -// FT_Byte* face_memory = face->stream->base; -// FT_Done_Face(face); - -// if (release_stream) -// delete[] face_memory; - -// face = NULL; -// } -//} - -//} -//} +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "../precompiled.h" +#include "FontFace.h" +#include "../FontFaceHandle.h" +#include "../../../Include/Rocket/Core/Log.h" + +namespace Rocket { +namespace Core { +namespace FreeType { + +FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream) +{ + face = _face; +} + +FontFace::~FontFace() +{ + ReleaseFace(); +} + +// Returns a handle for positioning and rendering this face at the given size. +FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size) +{ + UnicodeRangeList charset; + + HandleMap::iterator iterator = handles.find(size); + if (iterator != handles.end()) + { + const HandleList& handles = (*iterator).second; + + // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same + // string). + String raw_charset(_raw_charset); + for (size_t i = 0; i < handles.size(); ++i) + { + if (handles[i]->GetRawCharset() == _raw_charset) + { + handles[i]->AddReference(); + return handles[i]; + } + } + + // Check all the handles if their charsets contain the requested charset. + if (!UnicodeRange::BuildList(charset, raw_charset)) + { + Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); + return NULL; + } + + for (size_t i = 0; i < handles.size(); ++i) + { + bool range_contained = true; + + const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); + for (size_t j = 0; j < charset.size() && range_contained; ++j) + { + if (!charset[j].IsContained(handle_charset)) + range_contained = false; + } + + if (range_contained) + { + handles[i]->AddReference(); + return handles[i]; + } + } + } + + // See if this face has been released. + if (face == NULL) + { + Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); + return NULL; + } + + // Construct and initialise the new handle. + FontFaceHandle* handle = new FontFaceHandle(); + if (!handle->Initialise(face, _raw_charset, size)) + { + handle->RemoveReference(); + return NULL; + } + + // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face + // releases it. + if (iterator != handles.end()) + (*iterator).second.push_back(handle); + else + handles[size] = HandleList(1, handle); + + handle->AddReference(); + + return handle; +} + +// Releases the face's FreeType face structure. +void FontFace::ReleaseFace() +{ + if (face != NULL) + { + FT_Byte* face_memory = face->stream->base; + FT_Done_Face(face); + + if (release_stream) + delete[] face_memory; + + face = NULL; + } +} + +} +} +} diff --git a/Source/Core/FreeType/FontFace.h b/Source/Core/FreeType/FontFace.h index 64536b649..2d5633964 100644 --- a/Source/Core/FreeType/FontFace.h +++ b/Source/Core/FreeType/FontFace.h @@ -1,82 +1,69 @@ -///* -// * 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. -// * -// */ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ -//#ifndef ROCKETCOREFONTFACE_H -//#define ROCKETCOREFONTFACE_H +#ifndef ROCKETCOREFREETYPEFONTFACE_H +#define ROCKETCOREFREETYPEFONTFACE_H -//#include "../../../Include/Rocket/Core/Font.h" -//#include -//#include FT_FREETYPE_H +#include "../../../Include/Rocket/Core/FontFace.h" +#include +#include FT_FREETYPE_H -//namespace Rocket { -//namespace Core { +namespace Rocket { +namespace Core { -//class FontFaceHandle; +class FontFaceHandle; -///** -// @author Peter Curry -// */ +namespace FreeType { +/** + @author Peter Curry + */ -//class FontFace -//{ -//public: -// FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream); -// ~FontFace(); +class FontFace : public Rocket::Core::FontFace +{ +public: + FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream); + ~FontFace(); -// /// Returns the style of the font face. -// /// @return The font face's style. -// Font::Style GetStyle() const; -// /// Returns the weight of the font face. -// /// @return The font face's weight. -// Font::Weight GetWeight() const; + /// Returns a handle for positioning and rendering this face at the given size. + /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. + /// @param[in] size The size of the desired handle, in points. + /// @return The shared font handle. + FontFaceHandle* GetHandle(const String& charset, int size); -// /// Returns a handle for positioning and rendering this face at the given size. -// /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. -// /// @param[in] size The size of the desired handle, in points. -// /// @return The shared font handle. -// FontFaceHandle* GetHandle(const String& charset, int size); + /// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed, + /// but existing ones can still be fetched. + void ReleaseFace(); -// /// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed, -// /// but existing ones can still be fetched. -// void ReleaseFace(); +private: + FT_Face face; +}; -//private: -// FT_Face face; -// Font::Style style; -// Font::Weight weight; +} +} +} -// bool release_stream; - -// typedef std::vector< FontFaceHandle* > HandleList; -// typedef std::map< int, HandleList > HandleMap; -// HandleMap handles; -//}; - -//} -//} - -//#endif +#endif diff --git a/Source/Core/FreeType/FontFamily.cpp b/Source/Core/FreeType/FontFamily.cpp index 0cd4349e0..c389c89b9 100644 --- a/Source/Core/FreeType/FontFamily.cpp +++ b/Source/Core/FreeType/FontFamily.cpp @@ -1,79 +1,58 @@ -///* -// * This source file is part of libRocket, the HTML/CSS Interface Middleware -// * -// * For the latest information, see http://www.librocket.com -// * -// * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd -// * -// * Permission is hereby granted, free of charge, to any person obtaining a copy -// * of this software and associated documentation files (the "Software"), to deal -// * in the Software without restriction, including without limitation the rights -// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// * copies of the Software, and to permit persons to whom the Software is -// * furnished to do so, subject to the following conditions: -// * -// * The above copyright notice and this permission notice shall be included in -// * all copies or substantial portions of the Software. -// * -// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// * THE SOFTWARE. -// * -// */ - -//#include "precompiled.h" -//#include "FontFamily.h" -//#include "FontFace.h" - -//namespace Rocket { -//namespace Core { - -//FontFamily::FontFamily(const String& name) : name(name) -//{ -//} - -//FontFamily::~FontFamily() -//{ -// for (size_t i = 0; i < font_faces.size(); ++i) -// delete font_faces[i]; -//} - -//// Adds a new face to the family. -//bool FontFamily::AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream) -//{ -// FontFace* face = new FontFace(ft_face, style, weight, release_stream); -// font_faces.push_back(face); - -// return true; -//} - -//// Returns a handle to the most appropriate font in the family, at the correct size. -//FontFaceHandle* FontFamily::GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size) -//{ -// // Search for a face of the same style, and match the weight as closely as we can. -// FontFace* matching_face = NULL; -// for (size_t i = 0; i < font_faces.size(); i++) -// { -// // If we've found a face matching the style, then ... great! We'll match it regardless of the weight. However, -// // if it's a perfect match, then we'll stop looking altogether. -// if (font_faces[i]->GetStyle() == style) -// { -// matching_face = font_faces[i]; - -// if (font_faces[i]->GetWeight() == weight) -// break; -// } -// } - -// if (matching_face == NULL) -// return NULL; - -// return matching_face->GetHandle(charset, size); -//} - -//} -//} +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "../precompiled.h" +#include "FontFamily.h" +#include "FontFace.h" + +namespace Rocket { +namespace Core { +namespace FreeType +{ + +FontFamily::FontFamily(const String& name) : Rocket::Core::FontFamily(name) +{ + +} + +FontFamily::~FontFamily() +{ + +} + +// Adds a new face to the family. +bool FontFamily::AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream) +{ + FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream); + font_faces.push_back(face); + + return true; +} + +} +} +} diff --git a/Source/Core/FreeType/FontFamily.h b/Source/Core/FreeType/FontFamily.h index 58d9025d9..f95be801a 100644 --- a/Source/Core/FreeType/FontFamily.h +++ b/Source/Core/FreeType/FontFamily.h @@ -57,21 +57,7 @@ class FontFamily : public Rocket::Core::FontFamily /// @param[in] weight The weight of the new face. /// @param[in] release_stream True if the application must free the face's memory stream. /// @return True if the face was loaded successfully, false otherwise. - bool AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream); - - /// Returns a handle to the most appropriate font in the family, at the correct size. - /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. - /// @param[in] style The style of the desired handle. - /// @param[in] weight The weight of the desired handle. - /// @param[in] size The size of desired handle, in points. - /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise. - FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size); - -private: - String name; - - typedef std::vector< FontFace* > FontFaceList; - FontFaceList font_faces; + bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream); }; } diff --git a/Source/Core/FreeType/FontProvider.cpp b/Source/Core/FreeType/FontProvider.cpp index 774985a2f..17a4f403d 100644 --- a/Source/Core/FreeType/FontProvider.cpp +++ b/Source/Core/FreeType/FontProvider.cpp @@ -183,28 +183,17 @@ bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& } } -// Returns a handle to a font face that can be used to position and render text. -Rocket::Core::FontFaceHandle* FontProvider::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) -{ - FontFamilyMap::iterator iterator = instance->font_families.find(family); - if (iterator == instance->font_families.end()) - return NULL; - - return (*iterator).second->GetFaceHandle(charset, style, weight, size); -} - - // Adds a loaded face to the appropriate font family. bool FontProvider::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream) { - Rocket::Core::FontFamily* font_family = NULL; - FontFamilyMap::iterator iterator = instance->font_families.find(family); - if (iterator != instance->font_families.end()) - font_family = (*iterator).second; + FontFamily* font_family = NULL; + FontFamilyMap::iterator iterator = font_families.find(family); + if (iterator != font_families.end()) + font_family = (FontFamily*)(*iterator).second; else { font_family = new FontFamily(family); - instance->font_families[family] = font_family; + font_families[family] = font_family; } return font_family->AddFace((FT_Face) face, style, weight, release_stream); From 870ff44c9b45ff01cfc870b455b181c1d48e4575 Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Sat, 29 Aug 2015 20:48:28 +0200 Subject: [PATCH 03/13] A lot of changes --- Build/cmake/FileList.cmake | 15 +- Include/Rocket/Core/BitmapFont/FontProvider.h | 101 ++ Include/Rocket/Core/FontDatabase.h | 4 +- Include/Rocket/Core/FontFamily.h | 3 +- Include/Rocket/Core/FreeType/FontProvider.h | 6 +- Samples/assets/Arial.fnt | 273 +++++ Samples/assets/Arial_0.tga | Bin 0 -> 4194348 bytes Source/Core/BitmapFont/BM_Font.h | 184 +++ Source/Core/BitmapFont/FontFace.cpp | 131 +++ Source/Core/BitmapFont/FontFace.h | 68 ++ Source/Core/BitmapFont/FontFaceHandle.cpp | 450 ++++++++ Source/Core/BitmapFont/FontFaceHandle.h | 137 +++ Source/Core/BitmapFont/FontFaceLayer.cpp | 122 ++ Source/Core/BitmapFont/FontFaceLayer.h | 78 ++ Source/Core/BitmapFont/FontFamily.cpp | 55 + Source/Core/BitmapFont/FontFamily.h | 66 ++ Source/Core/BitmapFont/FontParser.cpp | 0 Source/Core/BitmapFont/FontParser.h | 0 Source/Core/BitmapFont/FontProvider.cpp | 247 ++++ Source/Core/FontDatabase.cpp | 75 +- Source/Core/FontFaceHandle.cpp | 211 +--- Source/Core/FontFaceHandle.h | 51 +- Source/Core/FontFaceLayer.h | 6 +- Source/Core/FreeType/FontFace.cpp | 8 +- Source/Core/FreeType/FontFace.h | 7 +- Source/Core/FreeType/FontFaceHandle.cpp | 1024 ++++++++--------- Source/Core/FreeType/FontFaceHandle.h | 299 ++--- Source/Core/FreeType/FontFaceLayer.cpp | 242 ---- Source/Core/FreeType/FontFaceLayer.h | 142 --- Source/Core/FreeType/FontProvider.cpp | 2 + 30 files changed, 2610 insertions(+), 1397 deletions(-) create mode 100644 Include/Rocket/Core/BitmapFont/FontProvider.h create mode 100644 Samples/assets/Arial.fnt create mode 100644 Samples/assets/Arial_0.tga create mode 100644 Source/Core/BitmapFont/BM_Font.h create mode 100644 Source/Core/BitmapFont/FontFace.cpp create mode 100644 Source/Core/BitmapFont/FontFace.h create mode 100644 Source/Core/BitmapFont/FontFaceHandle.cpp create mode 100644 Source/Core/BitmapFont/FontFaceHandle.h create mode 100644 Source/Core/BitmapFont/FontFaceLayer.cpp create mode 100644 Source/Core/BitmapFont/FontFaceLayer.h create mode 100644 Source/Core/BitmapFont/FontFamily.cpp create mode 100644 Source/Core/BitmapFont/FontFamily.h create mode 100644 Source/Core/BitmapFont/FontParser.cpp create mode 100644 Source/Core/BitmapFont/FontParser.h create mode 100644 Source/Core/BitmapFont/FontProvider.cpp delete mode 100644 Source/Core/FreeType/FontFaceLayer.cpp delete mode 100644 Source/Core/FreeType/FontFaceLayer.h diff --git a/Build/cmake/FileList.cmake b/Build/cmake/FileList.cmake index 37d2008c5..5fe33a56d 100644 --- a/Build/cmake/FileList.cmake +++ b/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 diff --git a/Include/Rocket/Core/BitmapFont/FontProvider.h b/Include/Rocket/Core/BitmapFont/FontProvider.h new file mode 100644 index 000000000..6bc6b56ef --- /dev/null +++ b/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 diff --git a/Include/Rocket/Core/FontDatabase.h b/Include/Rocket/Core/FontDatabase.h index 142525867..dc83f79e9 100644 --- a/Include/Rocket/Core/FontDatabase.h +++ b/Include/Rocket/Core/FontDatabase.h @@ -54,7 +54,7 @@ class ROCKETCORE_API FontDatabase enum FontProviderType { FreeType = 0, - Bitmap + BitmapFont }; static bool Initialise(); @@ -115,6 +115,8 @@ class ROCKETCORE_API FontDatabase FontDatabase(void); ~FontDatabase(void); + static FontProviderType GetFontProviderType(const String& file_name); + typedef std::vector< FontProvider *> FontProviderTable; static FontProviderTable font_provider_table; diff --git a/Include/Rocket/Core/FontFamily.h b/Include/Rocket/Core/FontFamily.h index a65aa1905..12876a4ed 100644 --- a/Include/Rocket/Core/FontFamily.h +++ b/Include/Rocket/Core/FontFamily.h @@ -28,9 +28,8 @@ #ifndef ROCKETCOREFONTFAMILY_H #define ROCKETCOREFONTFAMILY_H +#include #include "Font.h" -#include -#include FT_FREETYPE_H namespace Rocket { namespace Core { diff --git a/Include/Rocket/Core/FreeType/FontProvider.h b/Include/Rocket/Core/FreeType/FontProvider.h index e9c034e00..6e81f88f6 100644 --- a/Include/Rocket/Core/FreeType/FontProvider.h +++ b/Include/Rocket/Core/FreeType/FontProvider.h @@ -28,9 +28,9 @@ #ifndef ROCKETCOREFREETYPEFONTPROVIDER_H #define ROCKETCOREFREETYPEFONTPROVIDER_H -#include -#include -#include +#include "../StringUtilities.h" +#include "../Font.h" +#include "../FontProvider.h" namespace Rocket { namespace Core { diff --git a/Samples/assets/Arial.fnt b/Samples/assets/Arial.fnt new file mode 100644 index 000000000..0a01381f8 --- /dev/null +++ b/Samples/assets/Arial.fnt @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/assets/Arial_0.tga b/Samples/assets/Arial_0.tga new file mode 100644 index 0000000000000000000000000000000000000000..5a66e4423e44ac3c765469fa313c7d0f4e460bf4 GIT binary patch literal 4194348 zcmeF)EwpXP(&qI$pvOQU5C{Z<9s_}Bfj}S-2m}IwKp+r^7A+761mcPoh!zM00)apv z5C{YUfj}S-2m}IwKp+q;5C{a~vVXn$=@Tbz&bj8^r>fp_>wQvGW=2Lt=KRn6o@<}_ z!yo>!Km4QcH~#Q9{^sBON4b^wmp{UP`Vsz@kMMtggg^bm@V|eA|LP?8cMAK}h!mi_S~{F@(P z%B26vkMLiAg!m>?$N%#Y{)>;Goa_|n3A^my`3V2RM<5r=Z=ILrxBn{tmV2e9Y^UW< z;h*~m|IrP%xu&+;Q&jZNdkdwvo9)1UsYk6=ul#@ptY{8!qL`r>2fBR|Do z<@S|!exx%OK@grDoQg#)aBmT>e@PB-S_%&bHgG~E> z|08&ZS9_0t{UdBYe3B_U)vvwkG$;KNAK|3)&wm6ufBz$#%B|o3^GBd#zw{q}1Z|WT z*t}BD`LeOkieGgbzuPap8Sd&y86SW5Bk)P44s}gGGfjWy|gu{Q)i~lJ=yzN z+wb;Fc^~{vA6IF8BJKHXJbh|^o@L5UY5h`N>fYu0Lj0I(|Ba8Zb&^*nF7!5I^Ot^` z{WosLlf8NDPq8&s+y2{+a4IMBKD6E5GycW$&@`*q1-gzngL3^aVS94zU?&81o5zHsfV$K|V=riWW|NJBTD<9#? zp6*rPi%;{Z`R(Mx9*sTSIS)@=a^>{s&$5~Jyr0 zpuKm`{@;8Aw*TEn*mdnZ9lC7Z)k`mRd#Af!Di?MgGyl(g1n-`ncb78x&xF{`SU=F` zpZIYX@U#!B!+7F%wt3bqoqD(YE^mw(53!xGHT~UO5#Q$E)7+Z5K7Q#ZE%qMcW5>~( za_`Sv8+KxO@~Icw#LALRJY_pAe+u?y|G`I4_8)!(`IFugnRlrz-t80pt>exn&oX23 zt@|YZq>sJx^RImb{mEP6;i^AhJ;Q$2cl*I`{Yo2BPkiir z!18&A9nH)869`{Z|d zo;UKu&JIb(cE(T2(q`XDqAzwQFnviIXXcJ6j}4jgjl8?KsWa2g#IX_I-8JM+kKgIz zly+ZZk2igPCe5e&hOG0kJ=GPN{U$wqDYC@QV#@f_w)o9nFM5eHhoA1I_~$Eq(%w|w z_>BFI?RA}hyjOGnE|>Q%_~7d*D5tmWe@Ry61@+(UpJ)B_=(C&hQ#yT!zHrw!xBZXs zi7#_Z-tDUe=l_~_PV*5z_Cy(5XX|fLeolL+ZyNV0cO>T6v_G-)Y37J4?&Q4F+viz+ zp0dDeKErIWIWKKG#dA(%M`zmKrBBc9PJ^7?zx5GLb&}<-jV>FqySjFnd37>NIX|a> zB^!G7F;geDPvdDTZH~$w!1GwY$kIOV#vEjg$einJWS!c+PWjxooXR3g+mnA1JGZkl zR`L$q2e~UHKdsr@uX)q6&;3qx%%}Y9ImA3c?tMh}No-BnXKwfJZpXF+v%AL1$!FgcvbI<4w3RmynSe|`9StIlAcWhtzZd`6Ad_?99H1m;* z?JLan%B``^*w*dnNZV^D z%>MUuzBXR?2wQzv-q~jRyt_x(y7D<|oO~(QKXMk+pUHNZ>i}J6n>>eDK0dUY{`5g6 z*i*k!*PP$6GDi5&7qxxXv(w7y(Py{Ici#S*Zu-*RZ*TqNf0PeDIA&fm=a_r+gFK`3 zo{!k14Ps+5bB=jLyXINUyy`6G_dq$b>3h?MGzP+!%d3;m^jUiP{s`JuNwdKC*PT`&SvVsRe9=RM;?3W9rEm%m+0FW>Ln6guB?atV;W?aoTC)+#O)Amjuu`wp5 z94}?&>nT5_y^qsD)MdG+hFB1ng1tMQfP3;!4*TH9qOu%U$U`m1oSGC-v`>oxQdCp3Dm;`@ck4 z)+x_D!+e&=r|hqDTEER1PJGvoPn_&0oQdYXMB3TMzUyT3nRhUClYSbjJKxjnQLTUW zMC`@#*=sn1&$gzHDVu5MQ+IpzW!4vSz${N12fmcw?KgZYPMz8n`@|SO@#8#_eYrhO z>=Qft^RxFdcv$1@kM^9BZ~WR2KZ$cT<&#V-qj`Wb*f{Jxy?a2J^Ji+`OIezV11`6X8Vrw=EG(NevETIulQ(3 z&Xn)wHDe+3(VjnYzoOiJWj^0dd#*g=KEtN{+h*tW1G-oHrp$B3ZN9OJ<=H9UKIJoB zu((@4=QCs<$gf~N5?}R^^bNlYqbI2QmAW3wbcD>c``L}ryr0vUa`&PRI&@#&p4Xe- z3fY^zvvp^b^?1+Eu|36480gQLU-H{J^|@>JevLV2V=`+YpZc5n!rVNZIgi}?q_>$W zOE~Sr*$8-=&(bdSS)a5a_KBTe+1PVL_Acg!zs%R{jobMi<3pK{{ES~E=Q4V`T%D&m z%sU`gKK*YW+uxJ&?a%xkKVtc<^CbVH`{UH{d-L;^eScUa{!8|edCl0roAdLm)>8e@ z972}$^Xfh>c49hg*+g!SM8z?_7e9k58B0sIoIXjv2Qb%I@A^rriSL%9>ndRZP z+sKb+n7U*$yesqkQ$J~Sv316aOnmaUWnr4L!L;Astur=GXJ~za@2fUWzj-gdS5NtF z+bnyRzO%KzRDQSrKG~mS`EHv1_Pcf|&%KX%W9u8M&g=TkX%B166zBQi4;MUE#EN9Z3UCFm@@|zENo^Qu#>xoas zkom}2DgLiwV>xH&+;=$_c?ae@^W>H7l;^H-?rD^#?Nj$EZQRp8-LX2Kn1huYzkFox zMXr4N{n34(x`cVY-*w363~JB(vUoP%PG6aC_p|32ypQ=Vq{-B`=le=^j^i#j|4tHgAXSp$={l?AqBTue;kEQ8jrsHGEW;*3N z{_4KAel~&c^Y$*;+vGi*V&j7D_tvl6@4-jbYV*qJ8Mn+FV!t6)W)Eo`U}vmu{p7Q+ zq&xSWSugfJHg?(f%>8HHQ*`d)sXNnmHp-^%On=4BGoQ{?)7Pvcd%wsMU+I%a=V|;~ z+T6AKU0I%I>YdWoL%QkD@+ZA1v**h`3G>hX_Va1m)H!u$dbZ~-9h-SxAiJ|s7Q1(P zcjfu!ayLhq3*9}qr!c;=kDqs6_Cwlp=V!Mg=YxIrGXLaG#2!3$xsTlY8|B8K`uCb0 z+kC%}rzfOr$FI^?dG<3`ey8sAqyJr%(Nm^P(^rR;k&DybDSMi}vd#J0nli`B_M3S&I{Fl!w zoj#gjZv31g%K*v5@J5r{P##hG9?l&3RU)hJNNBx=q+_z+n(O&IJ{o0nbz;n2J z+xIxpo%e0V9sllE*n2+q`+k8;h>sb+O3r2UW_kLUxp(?VI&<>gXG|Y69lI%;>6GvI zEBo5*L%x2#QL&Ey$iAPa-;0lMxLOy!QM*p%ZqVFlZQGh;%Jlbn9*CYfN7>#lU~FzN z*3E0trz<3X7r!)Lx-)%eqipKV^jGZIXD@eUKkLXE7FptHyJb5+b+6LDmCdaGuFg~0 zNjCjS+e^{2mgs9@`O_Y2+Gby1uQ1oBsUvM2$~c*K&gu}h{we>`{Cq!*uhc*9=bzL) z>y0n5@nkGo7wpIAS*zWN?s1s!E%qGKN79%(gBYjLu{Ys!?!z+9qZ9kP*u2C~&Nx#y zYjF17o=F=#k2XzRX?}z)Pd*%;=)OEXd!JJ`b&2zh`1EXPgXftxGd=w#z2o>HkFEDE zzwcC>w=#D0dHQ0y&sX7f$9;oCF|<;6?VoQy_dzyW~P9^(}i<`LCS)`CuzZpTg|F z#+K)&Z?4(;nRAuTGjiCuOWZaY4}1N`?QS1_n*X&g<23y)bAvsGcI1vg8|_2(z94sN z^WKKc`%ovlxgRs1k)75m&zgR5^_v5>0^R&g&()kuPIupnlL>shQs2MNDVu5fJLFw? z9?vFbL%wzI^7ZpQoy<>P-S_kMd-0JuOaJW_80c7{JgU} z)n%;bOp)>(+iS#k*3Hu#VLV&swQKGhtg(Euji2y4`H9Ys>GCu8@zL?#$oW-Y*5vFj zqnDT;;i~>u>GyL5zp+o8Hqj@`{`!gE_`uDchmX^oNl%$?#j%-j+OWB>5vJ}-@=caK zan3N&wO^*IU6F}1f3chL>=*Ywf9iP7>{I7HG&*V9yEytYj?I+iJLZ$W|H&DVjk_bU zew^oY#*){5<+GlhHfQ@A+>90TioN0N6WRaHJ?r)(A0L^Q@|^G5K%ed$bMYS^$%{QN z`4d*L(^uJCjWKfNSA9Bu#5mC1=a<}_Tyffb_~Pdj=AL5n$$WGg<9wb%#vNPbU-7a1 zp4z=-+eSV*r!q2QFZ2A>-Yd5HIe)XirtC>P+hU(1@2oa$<;inLCN0o;rM}Hk({86d z*PVWTvt)kC9DCKrf~a-S)eD{9WnH@tWUsct$+7jXoWJ_AawL z@+p(fetV9YDZko>PbSl6=2v%Qb3@KKk_+K)0^cl57&MAUHSC&m3{5BPr80W;tzjFANi4e|L@7i z?2q3leLiK3@?{L?dkQboWXk3^o;BFlCf7i^&|6o#wWS*sh@Q22y!-lgrIGM3`Q9@&2DY7ZN|={xIzJ)tofM*3X1WX)!G@)3XP zSH8#S$?nci{GH-EyZk+=eM9c-@i_T0=ks-%hdleNC+Rtt#V1+H$+A~C`L)-Xy77^A zznc@xi?Nxpy7;xfpYl^(TV}q^oyF`o`Ze8s9?Q3u^n3N?9K;WQvkfyn_o-8!blUbV zj{aSoy3Ct*db5m8?kBLE-<4Wn;Kqq5H`H9u(86%r<&I+^Ml#|W$)OnYl zb~Alt7oAhg<|N;;lke!9%E+?spogXWmF_!VS9Xz4`@BD6B;{gxdd7nMw3%sT@4`F% zob~8QU-^rls~9)uN$blVf7>Q~-#E`Vf~$H@^7uQIk%b@M*&AQoYtZMYmCdaCuFg~0NjCj`^*5wBv;D|#Ki{=&wsY#v^wfEhwzqN* zkTXksS%HVhq({&?}ttQ(pewpKI1EMP5hV#b{+EewAyFR z$@%`Yw$sfXLo7c-z8UdFE*AD#SXsuha(VAV`sCNyQJFwj$iKIS%{*_uO27U0Wp(}? zbmrQ5CTAI&Z(hzayy(s|Z1x-OLZ*H0MwCaMap$)mk)7g*;^*d@0XwA#j>`-{7oGV(*XMJAcNMGYI{CM`Zrl?eZMBq#tMB?|au>UG&+p zzth{SGS=OPke~F^2k)NaWEWYU zFZtA+K9o7copW@i%}l5KDt`Cu?2N1Ul)my6omp=FFdmd?ukkU@pq*Y-=05fUHERB@ZNuaWFAzHIc3|(e|8`4IZu8fo6nSfcy;#5xhg)VEr0em zSGIJGh0}VSwuqI}qd(=+WWr8wz2slo-}{-enZC10*^INk&her=`@XwF+L`y&qe8@7gwfP2HrQ#M8%4v-e#h^O5{MBajK(HhIrvF7!Rn9wujvX_GZ) z&Y9Wkvx%=6)8%8XUukE4r!n=f((m>w?DCyfeL1h4{ArVO0X=sY<{Wz|&z^Zp8C$VH z-x-9SzT#VWd?=^uP9}Sb_%+@=XP!B_zKh2G>URo!3Ty=Z4R7yCn{(fw&b|M8S$zM# zPqO?5M69lG_O9i3NWY+`ENzJW)|YqYPu=h0ll@Z}*4{g=)|_o;|DNw!+Of-bp1-^| zeMWhH*Pid%V!r$>>$czdu-Xa`ttOaZjkN%!xr;fD#AHTbd4}tuZx?d|!I#V{&sp}+5*^Ixsubn=m>*sqS`n7kUZ+>5L zolC!DOY8UKBkSb5aT7ZBQl9_ndw%8}b7t0fve@6n`Aw`d&E0Q#pN=7QP2HKkYsar; zm%W2;RQl9x!(H1>Wm}f~lQ{K0(T&cJ*u+-6{kI1Qmpg+^U-E2~pT_!~-|1(k zr`=3%y`7)BNk56VpP6T$eD2Qo`8Rb$FR^`|{Ylp2=*>8~`&)DNIL-}M`?Nm71_bN1Qa@}{mkkF4 z_l)teV|v1D+e`ANe{e71JzUvLd2FUE`#QeK^S-X$%`Q)y?!H4<15)?9c((1c>D{(z zZ$Imdl(k4ZX89@YUWT4;{3*}0(mBaawq#*&+K0_^R^|wMD*nAU z<=gL%?gMw*^+_`QR$b}8#zX3!HZz^_tN8BOr_B?ecRG{fythalSGLxels%c}-}&3+ z<{3()!JAKv9pP%uc@ShBmo^~^x@+a}Mo9QRE(V2ELo$@E~v@^%a8%I}tefrGbg1T3l z@|m7{E$LZym(ISx_{{iwH%{;TDVxta(|=WVIj4zd8}8b6D%-N;pTw#6iEea$#3r`l z?eAULoqpEY?31T2>FoFD?Xt|T+0XCtQ$BM(Tjh6c+xAm;rnlZ_^87@9w=MEhUC#d5 zKPb0X@OL`Kwtd02v1cQ*cf?X`j9#&`W@Vp|vx)Y^x3ayiDR*wM7tfxCfAf;MwSmr6 z$T@0%4?pQ^lkXYcBM$aE;ioP(Vu8P@Yu?M=L;3V?FJq5_k7u-Jv~QtDMmO9~^V;+! z%}&rZ_b6<&S$oXeTYuWjvX__d+lnzce>i8arEg5zr1S2arRlR{uWiwpalZZQTNuo; zndU>7vd^TwOKhz(yB=-RPqq2#o$b2V=yRTL_R&`>zi;PBHvM62kE<`_460lm`m6V; ze{DbP*pTPn)nMa{i6^;oW7d1&lV0TP$#%G76^k*xcec;gCqCLMOnc*z45t&H^l2>hk7;{K&v`B5FW;iQ%lVE^_EV-^!aLb4 zPg+0EeCHV>7khvDJKy{LWj$0*Z`yetHv0Z9n|ev_eIQ#Q<=SWuXKdmk#)v#RFN>GW zOsD)5v(K~7v+YUuiO+XBx!<8@{LFgpY^`G{zdDajU((Uv^5ir2^|_2uXXBJ7&K{G$ z%wgWCxsYt$YsO~ApWTP=@yVC>l=|E~P5;(DeN$TmbB5>8Kg^f8@5`N(dp!Mo-le4f ze>sWWtm= zKayF4vp-0=bz7MbnK(A&_K#O*4E~hUGp|e^()J$8Fx-3Y?Dy?Kt@qBnbnW-HpP6@t zGAF;&n>MGkx&&pf)b|WdHt%HK7hm=s)9-2h$r;rgJ9XdHG0RWwKFQc*A8mh1$GkLs z?X+j0m$TFz@9BH{nR)(%DSMjM2ek>WIWA(af9p&72idEp`?_+DwSSKvu{zirAM)Ox zJh}WSSWoHb%d z-6uZZ=@>WW5PJH^^-jTn8@kVJJmrp{Y7WWW;*5KAKBN|PpF>%-B10W#*gg#e@{O27vn5* zoHfNBB73IHD}Ve5))eec_kFY9Nz)Uy{9XRZZ+TyypZT7;GySd|Q+K9+3A_9*%6=j1 z$z2_%vMt;BckNXETiMLE+|_w1JIVOV{cFnK#dDotpL_ki&sTO8^4%(T&KWbt&y@|i zv7~+U<SR09?|el!`=61PfuQ$BlL|9-=%Jibry zN#8g&Hay?nBW6FFzAEO|p7rD_-(L3qknX8HkxgIWt<0T)eSXHQSUz_Nbnf2YJ66VB z&W8HM)t)`=Q=a`mo>l&xo!|dz>z=3LcgH!mu-j$71RrOHj7ja^^O5&VrcAr(<{hLx z`ilD!<>o7QoZ1^bOzby}Z}%nigxz;u((lJ^>M)n`$%dYKt~I!UhT4(-{-F1 z+U|})=FIe=JKa;+mhJrHaFzb8Y-as;b)L#jGX652zWN(d>kQx4$tP=~vt8EIoJX_g zv(K5&xYO1!b`99AkcT?FTJ0I8= zD!U7w^K=$YJ@(7_?sn%#8RmP9oqo&#nYZlKQ}&fOZDBjp?|kLH-gBo7m^l~aOyzvV zPwr{R?O&V?@W?j}^?KKIKhp;KLf)-!FfYlqpX_l`k3C;(PH}!;8U3sGk~8Vm8D#p7 zuP5=e%U<~1_@6eZW6EYa-z!h;cHY3&`0&oe@|a8?()xh+Ypi&;yL{*G+T}Sj??i9M z%JsGFH~Dw0ym!yS?`Q7N@{KI*JKc4p4T&@EPmH58776CDr3#~;mg{eeXVsU zcRJ>S=(*v8<1}^R~8o?x}y5KK1Q8{gjz&jH}#nMn2=rr>8Y^>RBhWgFg9hZFk4O8e)F- ztk&E+-Ba0??fm3$mHw@4X8m_{p2|)#>rM7LIg8IaW;)-k>9d<<*^Bx;PuBEVp0qM! zKwI){R+;ZPWbF4k5LU4eOrLb8EN8>m?AS9#Uw^=J>m)yQBa7{mINwXB?MzP}-fzlq*S1-{)5__^<}_xo zQ10ye&L98r^(0Pv^i}78r|0X~rH`8P*Dk*8 z`|aP2fs6;SyfLDDwqd59u*x%~9W$Q3c6#p1*<9_(W2c?gJADYJ$nRo$o|WCzbCQ3R z&#YVDHHVqY!XWdSvZ;HOHlLd3y_-2!%yH%@dy=bhkvdPY{;pq{7f<6Z-xKI%-o9$1 za(e1vxAidp>^?AU-oCQ-nU{9iv`P9Dd;iv~t7qSSlaH_DPw^8ScJ9cctB;T+FMSv6 z4YJ0~`F-0w@n^i#^ZwqAx9vZ9V}%cEcw{?%vJdA&*tU0h?~={#!^SYValY-1J$sWa zKjrxlK3hirW%*;;dKn_k2=6-~OL{ zCq6&A@Ap1_Pd-ll%lJRd*(cqTZ1?Sx&PkT}&0K#fC$qlt|JifbZ*BLELB4Hdjii5i z=98Z-+xe59E&Hu(X1#ZHp2|)#`)=~5{gWR3yr{efGDX*08K+_GbL&9)NFW zVf#RJ+Y4qLkryVHr)fT&A5*V=fI93ePd;8XeP5S$M!sYB_Bjv4r+r4!r#gO38D`q# z&VSeAj?(&U4;$`V=QH`RU^CNCeE8;TUzk0=_hMY1?kKI#_F(2O^>_w-bbrJBY#X%G zyNX|JA^VCSb`2#^0wquaKMw(GNA8cEmF<_^*F0&V{fafpdSKrpe`WV%AO4kfC2hC< z&AQ#2@pn4^TmSd(U8e0!TTA(wGHHy+g#Ouzxib)d_UY3`o?Q8qOHUs&9la@= zY313M*$YJfE~du^yQx<{FB(^Testf@`|rue>^n(k{M%zoNB%V4efyoA{kwbV+`ZdR zU)h+qa{l?ux$C#Kd%_^+!#mwm*_Q466}u__t!$pwd1}u|mb5<)e)>1<_;Gi6 zD#y(`;#awEMSeqNZ^up`7hbtP|L?2xTY2(#alGK^8)DuM8}A6i(|WDo`>Vt%J5%|7jtK81JX{9<-m3;A=7Q%>*Xf6IK^HIB%|@>}PW_uSf=@v!sTh8}%- z%65M0>lbtd=~*VNj|f}-u1xvM>$m=L@$g30^o?D8%-PvE z%G_nHxO#tlKi!8veU`LGoUv%kndh`opRxbo@3iM|pFPLq^taRbp0n@W&3pWtOSX+? z&hI;nzgdo(@it}hic&+Wiw6xm)h6X51QZpjaWQhl5hY0(S1Kpzb7Bx z$b3tgi}g`s^_%orYWMATR?!!q-q*Ib=4sco+i7Ecu8n;BmUd~+Zu`uepEEDhpJhp( z{A^kBPh-BH>PGLYHhGR|KV?bJdah*F0ld6hd&=nD#q{(Qc310&zHZ-@HCJ1t$&}ss zx0d?7igndqi>PQ#a|Yv-8mt@3NhLr*qQ3^FPa^%^lgB#@CMRS&jECm-jw%Mu|UtjlO;7 ztS^82x&LO79({J&!zOj{O`d#W=N9MfV27ipZKNYw*u2A z+017gkSC-M)7!u4&-{`8D8`XI_TpKG^gG!sm;R;pwe^GME9mFmm2v-T?E6!XKJnGF z!_VeJd(xM2GxqiwI&Hp-L@eEe2+PZ`X8TG}|{lbG*yZ+b4bI zJKZ~ff2rk@>FF8lm+3eY`d(#ELC-jGw->`&J`1fyTSu?fCJ0*8MQ>HH|Q-98G^Lv(WgY>V?Yw<@fb$dqRgq`); znMIjco?LnM$hp_R&|V^UPxkg1L$ghu12cZ~)5-MXpF8`zo@@G7cgB}zC}t4_G9$< zqw5YK?RD-ZduhJ-V}iB4?_@&nD#ZS(T>G5Qqj!px(>wXFS60r>J8;JI9CXF&`R#u`AG;k+<~M@V_j^YdGi_u!p)SK|3zybtxvZ|bQRyZ9CB-zoF%XPI}aY|an$y)MTzeF(?QKe3zd`Q)E0y5TwX^h@Q&-PFZs>OD=T zt~>qQwU|%LF?7Z9?3HhO=Xhr)<=UF{YwO8d*Ob$v&yM}p)hE3t{aN4MdHUqa=_%j& z?bH0IPII;(O}6#qqifzi>5+XV@X1%kd2GoW{`wKf`#;6Tn*L{wo@AmsWlz)kySY2# zPAq>Kd#UGXtPRF7{gc16Q5hY&k%_Gn=5u#k#xouBsx{&?hnjb-ujX93?zOB7n^)>k zuV>9(iEn&QcYkc`Z`_$rR@yx8$?2*4X_)%bPr_5*^rk=e;hs0`$H|%HYTstB>v_Wy zC(k?o)^Pfl#!tQ0_ABn&h8}%(?05OhKRq|GvF;i(`cBp!b;wVj()yZnkiM3-n3t`o z){w0~^Pg!yyQk0K?CAYyvwe$tKDP0HTf6q&Iqmti`G2PUpW&bO&p3My&p+kTvrPFZ zY@6i6=$AP6^67o1&+K;Se|xSn-ss!o3({9((0JWG<;n9rJN8_3-i;-8bo8g~L!J-e zRJLU=&1bsXcITh^daCzT|K6K-W8TXgAeJZJ?^QjhUzcUXIb*qe{1-=ytB=(r<^Ed9p)OJuoA;+MX>GHa1F*Lz97Bc~(G|IZ`2@G3d~ zd;BSTX}4&o|`oydB)yAYx zy3_6|9s8?t^1QR0{i7?-e!h46YWqZT>!0;;_T$)|VtVx1vFC@sscX(qmbCY`>t`=WC7ekR0c;@BoHj_gTnewsGZ&s92pcR7CU(eQ|l z_hNn9_j)PcK2G^7U29YNnXz(r&WMjae|@Gta|A!e>9liSL~ag_T>dJs*B9LP>OZlW zv3bE6By#}YI9e;F-c=n_?j6keEoIZsyRLu-c?tRRiK0D_#O!`vv8*<1j8Pk7?bTA@$U=hJr#cJ_Vd9dctSzTAn}TUh7xDM6Y{S@aUew=&~Hx!>Bh!$ zX-o27jkR5PV*k>7={m<`PB#bHf1S=O=Gfe~d46XS>*w@!SNE0PJ9)|zU)7;~blibX z9eHx)Q!ec}l%a5qEYD}=KhKqYo-;(AODs=UIlg>jOy;?qufhjc&zR@M>Z&bxnJi7IM%e?joS9QKhU*$7>r5|~8t=D<)k%`IXwFQ?<~G%|7SQk74+v^hqf$Qa#q>^z$-oB1bcKGF}JKjagv zUGsg=OPMo1|JgG}o;dF)=TiNczJ48@#O6z7>WVDq+qsWQnV6hS+9WMZotb`>eqVl) zoou4_E@tcba$clw&UIgbhq8A*X8CN3^+Xx&gy(-WB zj`BTcq(1YbcOD-zb{Al+q#Jqcc09{xdh6|cbf3ntx7T7b=Wu1Y<5V79{V9FR*s&kY z-ZDB@F+KY1)W;8h(N}J)m}l)@cb*=(a(c>lKEBLZbj(>fGbocLQ${EH8JA+RosZs* zJ%_O6r~FIvnQrXufs8e0$vnqr{A^w4K{EHo`f>LESg0#^y>v21NegMyUHsDgUN`4s zYle4bO`^BY=J6XJVtpj?Qykr0mgltBoMkx=AfN3>8bjsYFPXHE@^|q|`?>y| zKWi&?^V>o8t9x%4KN)+uFUTFXJ`ATH1T_JlO5FXMLOfXY2f0dGm;U zXXcD>Kb<>%tv38s_|1J=#F!L`AeIpk5l^P_4{X;db50{)oC3hv(EdTG3%SU(_hlFe5O-A<5@n_Q|FY9uJ&P; zJ%hfRyC#LaYs4t7Wq5XGi9lB%A~L4(R)`OJ!773o+Wa5^3$A<{a1A9 z30HaYm&RFVmR+U!NI%SejLdfhV+3pWZ|wDVWrF@pHorf-N?!lCvCQ?&|$YnRmx7>q+)Kr|;*+DqZ7rwkc_H<;Fi*zPVz!$B*ZtE5ttj zJ%40RWBm}jm&fn_-M{$wjQ{wF?T%07+2bpd-ZndLpNg}6TINT#xhst57vxYj`?Y{svzupv=;d6Pz4^|6M$fvc zuG8Ip_WX4CG{?~ur;a=M)L|z~*;V?b`AnA&dm;0u{y*pb&-mH8<{z>X|Fqk?qGOzs zNed~zi(i`G>t_6B{EJU|@td-oU7T@Jw&Un-xv{6r9%Po8v&g4Ud1319box`)vy{uT zo$p7PyFT){kB}E)dx~Eg-*l3H7kjSwGf&e$jmLcd-FGkXA0MBIjc4|Ap2+&6Z2Gbf zq?@&ImR+Uk3#al|$+t3VE17-hN#DGtJnf49zFUZ`F-Tt^d!@eB7rm?aO5YeT-|8QG z-Z}ZQuF}`uxlU*Ahxf_OI;0KZojF+jC;k1rbjZ9ndz-Aa{8-O+zyBHaPtO_I)%($Z zo}4G+=d=3Gc=+LIel*wK&CSlS-gWw`Sbm>x)1IGAU%T`peHe3pBY9$<@o9~AM-qMg z&E1~zJY!-kGv~!;Vr;X{(~mssK=O&_{w_YR#!Bj+ey41v`7YaeI>J+V^j=nfZkKX#`q=60 zt2}4hQ(se_ux z0~zPu6*;}xW@&O^%fDJ?uGJs(outj7(z}lI_tRQVmt5O2UY;^cJy(0=lwZZ#n)yF$ z-Fa>H@&9hTs>gE(Cl2%dr%iLt${s3ZPvh{zjm@hC=Xbr!-|4<(=eO2eCZ4a(eVnZMJ{H$M+iVX6L7ka(eXX?L1w3RduE<)1FKj9di3` zVd^CPDmj-$=huq$H|^Z(E}8J8-k0V#-JL)A$lb8HL-`Y%_&Mo1FvAP=toyR>CeQ|E6Ml+XH_XW8*Q zU;S+Q^VxPf>+-$}`^Go^;9Qy&IdKO+U}!Z0#AGUC8o0 zDHrSCfGg5 z^60%Qro__Rh5WfAp>2?%ULr zHAER*A$qUe`M*4_&-kll`R1Sge)Sti=L>aY&Y5)^$K=X$Mlwgrzhjs=z`RV~o+q+d zNB+iN`IM*q`L>n!#6PZ1osl`GMB%k zum4(Olo?+n(!$i4=~wBie5R+))AT$0?8nU|*46Cw#PWIf^zQ0(25`Qg^(9TN{LWte z^s|@Q`E5&&K0ReSzxDsp@|kB&W5#m}PoC+e`Aye3hRnUz6MH(_$DQ3tH{&zoHus_K zhEBewkIY?}1GfIuP5Lu2f6?E*XWkx>p7mqOW2=11PwD9HGItB+qwM|giO!Wx%Ek7v z^o%q4E1Ue5{WQ;C+3@!ysGAStFn6YD&$Q3lXg_X#)fP<6v(7!I@7OsL*pK8MNStqY zoZ_r~0P+lvYRHNzUDDg_HhC_R{{Qub&vxRAI874Rn|OZ_T$>5Jo|F}J^KrB`oHq@qn}MbT(uW#ZOt=#P9Zwt z`Ap`L^mk*?J7dpJ&Z1c#uFi6q8}&>6Up0RF_qfRt>`|0wpPTpeBXfIvr(XG_^{zMMSXSw&2yV8`;IQx$&JEf=3S$-vt&bxAYxdX>Kb~Da9 znDg2!PkPt2^YpfC=AWdu4{g)`aWs!9*FX6pmlrN=dlOyJoNVW6FN9qqm^4* z$P(nqmD7tnu`(g~8NW(CU*@^k=6SNFOyAOXYX(kycy4PKefu=B$rGF=XXYaYZN9*g!k9Vj1-SfxR z8k&8-SUzQqpApcX^*wub{I}J+cRKaA?jJt_nek#w7)Qq8wAtzHW0%kTNtgeOTYD?d zCV0+ioAmTy92-+)?g^ulcwtvn*}PIx)+3I`!Pe z*{8-fy2+nnW0xML%CBt9rOHlijm?wz)CS|6t?xg1*Qc?cIo4WwRaf@kvmX2SoXcY8 zdG+V1m;1_jhce4^KILP|ciI{iUYWP)r0#cd{6$Y*U(Q;f?Wgw;yBX(Gyj&`}341wr@P?rhLc0mhP-))-mNt&+?g0`HVA% zPuVGb<>yKsAMeW3AKu-ED(8!SeD8SIwe$41Z04V&`N){CUy?R&WqwwkwRiSweVBh| z5jyWe*5%VU$~lt1_%WXD{Hs^_9Cz|L7sZeGwH!GIPSdhuXSq%r)eDkDc$*^E^lYF1Q5dNVzB^9-kRd2F7<)8`X?I zdEc6ybu9LYH!pU|_;I(KH9|ekMsw~@n|3_cD(jLl6P?uiF5dcl=y&Y2;c9HhF0uK* zc=0^D@6$;;qJN5?=xCquLKnA_AN6||-V-j_W3u^6(AP%&$nP(*zrc2m-So5coBdol zKV)C~S^doI_Q%_|JUO1(uRYcGF4+HU`r4G=9eF1Gj7;#H!YlXezs4~e?~jFXA^$Ge zd(x+ucPGDtvgqpL^vzRSFL%uLp~~n9TQB)n>8pIEQ$FKaKGRbt=~+J0DWCBypXsS{ zO25;c<>oebfG0m>x&OQ>k9_)!OnfDe&bxAR8=c%A#cs#S>0Ql*^py*-edWI8-|0;K zt27^BmiczhSITn-IRCEPIgC$p-5hiDg{+gx<-Irhr+IIF*Nv~cdqz5GlQG1X4fI_9>#vwoTg5(abT|7`pyaFbNvQK{U~hmtxUh2cKq9wx8qqp(_2seUHQqTvY(fLy@q#cPP}U6XWsdhu6fA(ma!N;F9pOLnCBk$=G4#JtMipHzvqOsC-sT*P0m=Ha(Vj7r#wF1#dE%Sr#t;89h>A6 zTQAK~c}DY6?f|ZAVk@?8(KBDmU)lIpuFQPB*QYBR{_aBT-o^0|y{rD6{h4{3jq|2C zTAy?-*PqD6)(!iL$xB)G?Wt?V`F_YJ-5snA%7oLJ8DHD(Dj)rf0r}mBuWZS)ejBSN zz4$+sMfOfd|IN~(*{k&XHvi1Jvu(5OQ=arJ_Z8JAKf^nC*%vr}APHx_@ z#-=PBa*xR$Te{9`d0(mDxmcMvJ}{yio3u%}F+`p_4E@6zOU8#iS>`x(kSCGuDRNL zPv&>6)&l#e06G zx>FXt8K->8cG}$pJ#AI?#3uh9Q1&W!Hdtr9wI<{Gw4UA8Q~s`Q`u2NtuI_*APn6p` z(9iFo_d8Q2WXy!uOZxf^h`VL|*z-#J=I$Pr|Eq6Q{3zE?<7>vsgekjAzqDWf&AqT^ zv-i2POPRjM+F3QS8Rz_p+mt6Ap7bJ{u|BQe;N*T~mPs3z+MDNapKW|y{ku>D zo!75Cn>klmp7TlkBl^1?GoQMr|5?7%KeK-3V*C8NcJH#Qy#DHWjcGb!`OITic9GK+ zlHaj@pub0+?{+V%@BeGeWTN2_k zd9mLTY0H!~T>>Rg0)NQ_oClnZgm-6y)4X`~?4Qx)!~QD2$8z={`;3pNoA0pB7yQP5 z&RD*KW?wRYlR15`NwB9-=1w90rf$-oiTRFx>iJBZ^Og1Po!ygq?2+ij-<^&7l#fsP zf6Ti2^uES@PtKzGZR=e<@1ARxzw?uNr_D}JA2`Tg?ZGy$?Q7?=&)N3{(X-!EAGVRr zSeYo>>R>i1}5?q2Tfl+pKY%?au6+s1i?KjUbZ$)Cno^xTEuppLm$OSw2> z)fmoqp_FTrx`oJoHvP2gD&EhK{)YXP&6NMr`k7C>6ZOPD`K&kT=+7_y?g!JKeXpdS`Q++;jLr;vJ9kdmOgmf5wMf~M-<9$!oaU*tSvh}VLHZP4rQhp5 z@f&vgJgttb>8W?tacaYqz0;lLo>kw)*xjsl8)N2OY^QF1=ZiNxbvoxDoI{lRPOfa~CjFUs``Gop%X@d~vnIdOO}p;&!k#X@*u0D9UMaeF z_1IU?vxk`V+}WJUQrEjUw)s8b{JlrY#A#P}+9&Xh^VCb){!%%;$nIjC=({&L=_wOV zWn{0?>+)?Eeb1%LSg`*gKkdP$y}5v%K0oC%o$qb-hEtw2IUn|bk%{faFvjib>`yOq zhPwj!8SMS|79#)I^!0D;yP7Na`8j8gt37|7Gx2BjoprP)cXjcTICq@>k+ z`x*7M?P<{d{9eHCl;n5tyBz-f{zO^Ev$M)+jtEcX^x0aMym$E-ayO`sDNovZYMoAg z#_4Cj#MxUL1^z$dH*2Z;apRl4eveVcW&Hkw3LgB2kEltX!Y-fRb5kbHTqVtq`6F{7 z*$m#%Y0inxsU2i@<@p|wzH{Xxa(eu+i)_ZbuAQg5Wi$UIZ9ky?tG}0N_w%#fK(tPPA&EM9YYrl5Q zy<6tp$ra&;bz?p4gUa8MTSr{bhfbiI1EK{LN=%<^}KF z-rJcc@>5JtTTkuGU5@gM-=9rC=gF%xUCt`Tk>?L{b7r1ta@ps}uj;41>05p3#gkuU z`EHxvVr_kL`dK@EHvQS&oz`w)%AKFd^i6kHSv$=8zWbT?jp4}WeHx~j=ge>VJU{&L zr5-~6j`>AUiLbFgpNcBg#y7wk^u zyRMyQvt={?Bz>y4vJxnP5-5Scd;&SY_s+=V#@$=ip!n^B+N2-uH?g?@Kx+Y=ez!V_IO zFYWL3wI_Sg+;g1#rM=$Ushmt7%-)$V@0MIFuYTotk-HCa#&P!`O?DUjMw1VF^su)t zo@amMxlj4o^m8Wi%=$<;xX;j^(%y{rp(W{%42L!i@w-9 zAy=OF{g&yr^|)6+-Nv-~rD+0!?->l2>Gc)a_Kb?R(f0wquaB~St-@Y@iuSF?|p z`?n`G+Z(d8PjHrUK5!0TYkzCK&)=@uFXh{vbBA*gJ97K1>?fU*?5muOlnXg`ymEiO zPdl}B>So_#AL2Z#jq0)2&eGoRn7(me%tV$shT^Q5KJ-1y)AQt4 z^xgSh`8Otaf6yN7+-;ZVN4a(+{A~JZ*N*c%TQ0938LN2E%Xi_d5!=Q(X0FX#%+B3r z?ggWtI?b>8uXPk#x|ye=JLA~lO*i*NQ|IZ~JHDpvOz-liey5M7OP~Zwpae>w1b$8e z_8(d6pT>C-`;XiKT-iF0?tO}VQqHYccJ@Q_3>LlAeHU-t(|4BWq#nP`CG)L<@08!w z<2mfbwyr%RnLYNj&+o{62cB~2?PHgp@^|Og_)F}rV%8J+jJ+#*&LZ}vsWUpsKZ&=E zGqJvwvzooJZ$vr!ziV6k&G@Pv(YY#*{M07z?rIP2Or*`}^J4jZR^osA)=%^;zb}|< z)0P>(YyZ3Q=}Y=fU;CBoOS!+B_OX4}W;TAytp7|tcy2y(%*6jyoVFNC#*gvJ-uWkf zov+xtSNK`=waYxHjrzX!Iwv|WUi}8b{PN^HnP>j2zIypL?zKlO&rf{LnEum$XN%p> zrazx0Y0oVr-?#)ypae>w1WKR;e(wZw9((PAp8a<+@om@H*>3={ueCpyC(n2PX(R3X zr*HGlANgLQcHd2XC%1Q;HfhkRFDCiu;|HaUl>&v{AOx2$Q~bP1F|36wwylt2lTKnavU z36wwyl)&$wK<*np8zXaP^O^Ecj=yQU)6s2Q0wquaB~St-Py!`T0wquaCGa%@zD4`Z zXMVGr-`4tjKOX%S)c0fGkp;hDp1;}l{olU{6?@;D{l;~E`}Uh>zb|&q6U(QyIs3hf z>A%xSd3-0u+sy2jOoVJO>|S%BDYQA?=XXUgvjbZ9$rB>rERv$+{+(%m z10hY8e=96!e=;F=0QvU=XC0qOzr6LoB~St-Py!`T0wquaB~St-Py&CQ3HbYWXG#BV z*XH2+cFvi*EP4O#8J(PQ^KaheEG|~Qzj??0M`C^jKHO1A`@MqS9Qb?xv?cc!%7xVV z%DwWw`8)TgOqxu7>V*lpXZCLvI_LX0qMg^tqMz9BE$Aos_vV!4&PDs!rhLZaY5$Zr zT>>Rg0wquaB~St-Py!`T0wquaPYF0DJBRxHzH==*vG3Ak&cDiqlTT;={2su!a5_2v zPJQ;|Q}#=w`4#x`|10yGhW!7j$vuN_=f1_$@y%V37GAkm-m^OMze@h_2Whgc=e+Ot z1?2nx;YFq{EZ7Rp@B8lv@;4XxT>`s?5-5QZD1j0vff6Wz5-5QZD1j3AH3|54;&WD3 zPtMQ2qdVU!6LuT?eL(IH{Kh}`2Y*%Pf9=x-zx&rN-~XlEQKapDw1WKR;O5iVnfN#^U6aMRrpR}{I-?b+{pT*z) z`-bg|o&P6y%JZB1tKa{}-@7>e?&A1}j_>_s+9XIj^XL1!GyeQ7zP!Mmj`ZuR{rCU= zpZksIrLM*$Py!`T0wquaB~St-Py!`T0wwS>6Ug~I{~q5TKZ0|zv$J;RoBrSW2)=VG z6Wj+Vcdqu0-#IzIt0zz3m%cNz`vd1@`P3)G}Wn{r!*Nte*3|zXu?5zW;mwFgR!XckD6p z%|GYv9fzU6!_Pf}SUzQqOP~Zwpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w z1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR; zN}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQvpae>w1WKR;N}vQv zpae>w1WKR;N}vQvpae?b|8IwmN&p6-003G@TPQpj3hIXalNe(^cM;Bj0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*Vq&w)MP`o)UT^J($a Fk}lps>k$9| literal 0 HcmV?d00001 diff --git a/Source/Core/BitmapFont/BM_Font.h b/Source/Core/BitmapFont/BM_Font.h new file mode 100644 index 000000000..040d6345a --- /dev/null +++ b/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 +#include +#include +#include + +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 diff --git a/Source/Core/BitmapFont/FontFace.cpp b/Source/Core/BitmapFont/FontFace.cpp new file mode 100644 index 000000000..bfb2c0b95 --- /dev/null +++ b/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 + +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; +} + +} +} +} diff --git a/Source/Core/BitmapFont/FontFace.h b/Source/Core/BitmapFont/FontFace.h new file mode 100644 index 000000000..178929622 --- /dev/null +++ b/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 diff --git a/Source/Core/BitmapFont/FontFaceHandle.cpp b/Source/Core/BitmapFont/FontFaceHandle.cpp new file mode 100644 index 000000000..93896f91b --- /dev/null +++ b/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 +#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; +} + +} +} +} diff --git a/Source/Core/BitmapFont/FontFaceHandle.h b/Source/Core/BitmapFont/FontFaceHandle.h new file mode 100644 index 000000000..d56e48cae --- /dev/null +++ b/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 diff --git a/Source/Core/BitmapFont/FontFaceLayer.cpp b/Source/Core/BitmapFont/FontFaceLayer.cpp new file mode 100644 index 000000000..35b2837b4 --- /dev/null +++ b/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; +} + +} +} +} diff --git a/Source/Core/BitmapFont/FontFaceLayer.h b/Source/Core/BitmapFont/FontFaceLayer.h new file mode 100644 index 000000000..6adcaa2a1 --- /dev/null +++ b/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 +#include +#include +#include +#include +#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 diff --git a/Source/Core/BitmapFont/FontFamily.cpp b/Source/Core/BitmapFont/FontFamily.cpp new file mode 100644 index 000000000..19dd32623 --- /dev/null +++ b/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; +} + +} +} +} diff --git a/Source/Core/BitmapFont/FontFamily.h b/Source/Core/BitmapFont/FontFamily.h new file mode 100644 index 000000000..f50f0bf07 --- /dev/null +++ b/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 diff --git a/Source/Core/BitmapFont/FontParser.cpp b/Source/Core/BitmapFont/FontParser.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Source/Core/BitmapFont/FontParser.h b/Source/Core/BitmapFont/FontParser.h new file mode 100644 index 000000000..e69de29bb diff --git a/Source/Core/BitmapFont/FontProvider.cpp b/Source/Core/BitmapFont/FontProvider.cpp new file mode 100644 index 000000000..0b4217cdb --- /dev/null +++ b/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 +#include "../FontFaceHandle.h" +#include +#include +//#include "../FontFamily.h" +#include +//#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; +} + +} +} +} diff --git a/Source/Core/FontDatabase.cpp b/Source/Core/FontDatabase.cpp index 0d71bf700..a44609e05 100644 --- a/Source/Core/FontDatabase.cpp +++ b/Source/Core/FontDatabase.cpp @@ -30,8 +30,7 @@ #include #include #include -#include -#include FT_FREETYPE_H +#include 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; diff --git a/Source/Core/FontFaceHandle.cpp b/Source/Core/FontFaceHandle.cpp index a0048e09f..8d524a171 100644 --- a/Source/Core/FontFaceHandle.cpp +++ b/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. diff --git a/Source/Core/FontFaceHandle.h b/Source/Core/FontFaceHandle.h index cc729ac34..d1ad9f451 100644 --- a/Source/Core/FontFaceHandle.h +++ b/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 -#include FT_FREETYPE_H namespace Rocket { namespace Core { @@ -54,51 +52,44 @@ class FontFaceHandle : public ReferenceCountable 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 @@ class FontFaceHandle : public ReferenceCountable /// @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; diff --git a/Source/Core/FontFaceLayer.h b/Source/Core/FontFaceLayer.h index 9e4c41bf4..d45cbfbf7 100644 --- a/Source/Core/FontFaceLayer.h +++ b/Source/Core/FontFaceLayer.h @@ -60,14 +60,14 @@ class FontFaceLayer /// @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 @@ class FontFaceLayer /// @return The layer's colour. const Colourb& GetColour() const; -private: +// protected: struct Character { Character() : texture_index(-1) { } diff --git a/Source/Core/FreeType/FontFace.cpp b/Source/Core/FreeType/FontFace.cpp index 630e2df72..bc49424a6 100644 --- a/Source/Core/FreeType/FontFace.cpp +++ b/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]; } } } diff --git a/Source/Core/FreeType/FontFace.h b/Source/Core/FreeType/FontFace.h index 2d5633964..941090604 100644 --- a/Source/Core/FreeType/FontFace.h +++ b/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 @@ class FontFace : public Rocket::Core::FontFace /// @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. diff --git a/Source/Core/FreeType/FontFaceHandle.cpp b/Source/Core/FreeType/FontFaceHandle.cpp index 6f1b4c8a1..f201d0bba 100644 --- a/Source/Core/FreeType/FontFaceHandle.cpp +++ b/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 -//#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 +#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; +} + +} +} +} diff --git a/Source/Core/FreeType/FontFaceHandle.h b/Source/Core/FreeType/FontFaceHandle.h index 7f75d8f5b..84810bc4f 100644 --- a/Source/Core/FreeType/FontFaceHandle.h +++ b/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 -//#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 +#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 diff --git a/Source/Core/FreeType/FontFaceLayer.cpp b/Source/Core/FreeType/FontFaceLayer.cpp deleted file mode 100644 index 504da0483..000000000 --- a/Source/Core/FreeType/FontFaceLayer.cpp +++ /dev/null @@ -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; -//} - -//} -//} diff --git a/Source/Core/FreeType/FontFaceLayer.h b/Source/Core/FreeType/FontFaceLayer.h deleted file mode 100644 index 600db258b..000000000 --- a/Source/Core/FreeType/FontFaceLayer.h +++ /dev/null @@ -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 diff --git a/Source/Core/FreeType/FontProvider.cpp b/Source/Core/FreeType/FontProvider.cpp index 17a4f403d..b0ca2db4a 100644 --- a/Source/Core/FreeType/FontProvider.cpp +++ b/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) { From ef425b35bc260d92aa8762e4595fb92aadbff978 Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Sat, 29 Aug 2015 22:51:28 +0200 Subject: [PATCH 04/13] FontLayer --- Source/Core/BitmapFont/FontFace.cpp | 141 ++++++++++---------- Source/Core/BitmapFont/FontFaceHandle.cpp | 4 +- Source/Core/BitmapFont/FontFaceLayer.cpp | 12 +- Source/Core/BitmapFont/FontFamily.cpp | 4 +- Source/Core/BitmapFont/FontFamily.h | 2 +- Source/Core/BitmapFont/FontParser.cpp | 136 +++++++++++++++++++ Source/Core/BitmapFont/FontParser.h | 68 ++++++++++ Source/Core/BitmapFont/FontProvider.cpp | 152 +++++++++++----------- 8 files changed, 365 insertions(+), 154 deletions(-) diff --git a/Source/Core/BitmapFont/FontFace.cpp b/Source/Core/BitmapFont/FontFace.cpp index bfb2c0b95..df0289694 100644 --- a/Source/Core/BitmapFont/FontFace.cpp +++ b/Source/Core/BitmapFont/FontFace.cpp @@ -47,77 +47,76 @@ FontFace::~FontFace() // 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; + UnicodeRangeList charset; + + HandleMap::iterator iterator = handles.find(size); + if (iterator != handles.end()) + { + const HandleList& handles = (*iterator).second; + + // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same + // string). + String raw_charset(_raw_charset); + for (size_t i = 0; i < handles.size(); ++i) + { + if (handles[i]->GetRawCharset() == _raw_charset) + { + handles[i]->AddReference(); + return (FontFaceHandle*)handles[i]; + } + } + + // Check all the handles if their charsets contain the requested charset. + if (!UnicodeRange::BuildList(charset, raw_charset)) + { + Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); + return NULL; + } + + for (size_t i = 0; i < handles.size(); ++i) + { + bool range_contained = true; + + const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); + for (size_t j = 0; j < charset.size() && range_contained; ++j) + { + if (!charset[j].IsContained(handle_charset)) + range_contained = false; + } + + if (range_contained) + { + handles[i]->AddReference(); + return (FontFaceHandle*)handles[i]; + } + } + } + + // See if this face has been released. + if (face == NULL) + { + Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); + return NULL; + } + + // Construct and initialise the new handle. + FontFaceHandle* handle = new FontFaceHandle(); + if (!handle->Initialise(face, _raw_charset, size)) + { + handle->RemoveReference(); + return NULL; + } + + // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face + // releases it. + if (iterator != handles.end()) + (*iterator).second.push_back(handle); + else + handles[size] = HandleList(1, handle); + + handle->AddReference(); + + return handle; } // Releases the face's structure. diff --git a/Source/Core/BitmapFont/FontFaceHandle.cpp b/Source/Core/BitmapFont/FontFaceHandle.cpp index 93896f91b..e887bc1e0 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.cpp +++ b/Source/Core/BitmapFont/FontFaceHandle.cpp @@ -318,6 +318,8 @@ void FontFaceHandle::GenerateMetrics(BM_Font *bm_face) void FontFaceHandle::BuildGlyphMap(BM_Font *bm_face, const UnicodeRange& unicode_range) { + glyphs.resize(unicode_range.max_codepoint + 1); + for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code) { int index = bm_face->BM_Helper_GetCharacterTableIndex( character_code ); @@ -368,7 +370,7 @@ void Rocket::Core::BitmapFont::FontFaceHandle::BuildKerning(BM_Font *bm_face) // { // 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; +// GlyphKerningList& glyph_kerning = kerning.insert(FontKerningList::value_type(rhs, GlyphKerningList())).first->second; // for (size_t j = 0; j < charset.size(); ++j) // { diff --git a/Source/Core/BitmapFont/FontFaceLayer.cpp b/Source/Core/BitmapFont/FontFaceLayer.cpp index 35b2837b4..92c6a02dd 100644 --- a/Source/Core/BitmapFont/FontFaceLayer.cpp +++ b/Source/Core/BitmapFont/FontFaceLayer.cpp @@ -41,8 +41,8 @@ FontFaceLayer::FontFaceLayer() : Rocket::Core::FontFaceLayer() FontFaceLayer::~FontFaceLayer() { - if (effect != NULL) - effect->RemoveReference(); + //if (effect != NULL) + // effect->RemoveReference(); } // Generates the character and texture data for the layer. @@ -77,6 +77,14 @@ bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, Font else { // Initialise the texture layout for the glyphs. + unsigned int size = glyphs.size(); + if(size == 0) + { + return false; + } + + characters.resize(glyphs[size - 1].character); + for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) { const FontGlyph& glyph = *i; diff --git a/Source/Core/BitmapFont/FontFamily.cpp b/Source/Core/BitmapFont/FontFamily.cpp index 19dd32623..dc1ec7f95 100644 --- a/Source/Core/BitmapFont/FontFamily.cpp +++ b/Source/Core/BitmapFont/FontFamily.cpp @@ -42,9 +42,9 @@ 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) +bool FontFamily::AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream) { - Rocket::Core::FontFace* face = new FontFace(bm_face, style, weight, release_stream); + Rocket::Core::FontFace* face = new FontFace((BM_Font*)bm_face, style, weight, release_stream); font_faces.push_back(face); return true; diff --git a/Source/Core/BitmapFont/FontFamily.h b/Source/Core/BitmapFont/FontFamily.h index f50f0bf07..9dafc243d 100644 --- a/Source/Core/BitmapFont/FontFamily.h +++ b/Source/Core/BitmapFont/FontFamily.h @@ -56,7 +56,7 @@ class FontFamily : public Rocket::Core::FontFamily /// @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); + bool AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream); }; } diff --git a/Source/Core/BitmapFont/FontParser.cpp b/Source/Core/BitmapFont/FontParser.cpp index e69de29bb..b0ecc2594 100644 --- a/Source/Core/BitmapFont/FontParser.cpp +++ b/Source/Core/BitmapFont/FontParser.cpp @@ -0,0 +1,136 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "../precompiled.h" +#include "FontParser.h" + +namespace Rocket { +namespace Core { +namespace BitmapFont { + +FontParser::FontParser( BM_Font *face ) + : BaseXMLParser() +{ + BM_face = face; + char_id = 0; + kern_id = 0; +} + +FontParser::~FontParser() +{ +} + +// Called when the parser finds the beginning of an element tag. +void FontParser::HandleElementStart(const String& name, const XMLAttributes& attributes) +{ + if ( name == "info" ) + { + BM_face->Face.FamilyName = "Arial";//attributes.Get( "face" )->Get< String >(); + BM_face->Face.Size = attributes.Get( "size" )->Get< int >(); + BM_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; + BM_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; + BM_face->Face.CharsetName = "";//attributes.Get( "charset" )->Get< String >(); + BM_face->Face.IsUnicode = attributes.Get( "unicode" )->Get< bool >(); + BM_face->Face.StretchHeight = attributes.Get( "stretchH" )->Get< int >(); + BM_face->Face.IsSmoothed = attributes.Get( "smooth" )->Get< bool >(); + BM_face->Face.SuperSamplingLevel = attributes.Get( "aa" )->Get< int >(); + //:TODO: + //BM_face->Face.FamilyName = attributes.Get( "padding" )->Get< String >(); + //BM_face->Face.FamilyName = attributes.Get( "spacing" )->Get< String >(); + BM_face->Face.Outline = attributes.Get( "outline" )->Get< int >(); + } + else if ( name == "common" ) + { + + BM_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >(); + BM_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >(); + BM_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >(); + BM_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >(); + BM_face->CommonCharactersInfo.PageCount = attributes.Get( "pages" )->Get< int >(); + BM_face->CommonCharactersInfo.IsPacked = attributes.Get( "packed" )->Get< bool >(); + BM_face->CommonCharactersInfo.AlphaChanelUsage = attributes.Get( "alphaChnl" )->Get< int >(); + BM_face->CommonCharactersInfo.RedChanelUsage = attributes.Get( "redChnl" )->Get< int >(); + BM_face->CommonCharactersInfo.GreenChanelUsage = attributes.Get( "greenChnl" )->Get< int >(); + BM_face->CommonCharactersInfo.BlueChanelUsage = attributes.Get( "blueChnl" )->Get< int >(); + + BM_face->PagesInfo = new PageInfo[BM_face->CommonCharactersInfo.PageCount]; + BM_face->CommonCharactersInfo.CharacterCount = 0; + BM_face->CommonCharactersInfo.KerningCount = 0; + } + else if ( name == "page" ) + { + BM_face->PagesInfo[ attributes.Get( "id" )->Get< int >() ].Id = attributes.Get( "id" )->Get< int >(); + BM_face->PagesInfo[ attributes.Get( "id" )->Get< int >() ].FileName = "Arial_0.tga";//attributes.Get( "file" )->Get< String >(); + } + else if ( name == "chars" ) + { + BM_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >(); + BM_face->CharactersInfo = new CharacterInfo[ attributes.Get( "count" )->Get< int >() ]; + } + else if ( name == "char" ) + { + BM_face->CharactersInfo[ char_id ].Id = attributes.Get( "id" )->Get< int >(); + BM_face->CharactersInfo[ char_id ].X = attributes.Get( "x" )->Get< int >(); //The left position of the character image in the texture. + BM_face->CharactersInfo[ char_id ].Y = attributes.Get( "y" )->Get< int >(); //The top position of the character image in the texture. + BM_face->CharactersInfo[ char_id ].Width = attributes.Get( "width" )->Get< int >(); //The width of the character image in the texture. + BM_face->CharactersInfo[ char_id ].Height = attributes.Get( "height" )->Get< int >(); //The height of the character image in the texture. + BM_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >(); + BM_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >(); + BM_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >(); + BM_face->CharactersInfo[ char_id ].PageId = attributes.Get( "page" )->Get< int >(); + BM_face->CharactersInfo[ char_id ].ChannelUsed = attributes.Get( "chnl" )->Get< int >(); + + char_id++; + } + else if ( name == "kernings" ) + { + BM_face->CommonCharactersInfo.KerningCount = attributes.Get( "count" )->Get< int >(); + BM_face->KerningsInfo = new KerningInfo[ attributes.Get( "count" )->Get< int >() ]; + } + else if ( name == "kerning" ) + { + BM_face->KerningsInfo[ kern_id ].FirstCharacterId = attributes.Get( "first" )->Get< int >(); + BM_face->KerningsInfo[ kern_id ].SecondCharacterId = attributes.Get( "second" )->Get< int >(); + BM_face->KerningsInfo[ kern_id ].KerningAmount = attributes.Get( "amount" )->Get< int >(); + + kern_id++; + } +} + +// Called when the parser finds the end of an element tag. +void FontParser::HandleElementEnd(const String& ROCKET_UNUSED(name)) +{ +} + +// Called when the parser encounters data. +void FontParser::HandleData(const String& ROCKET_UNUSED(data)) +{ +} + +} +} +} diff --git a/Source/Core/BitmapFont/FontParser.h b/Source/Core/BitmapFont/FontParser.h index e69de29bb..b426d6396 100644 --- a/Source/Core/BitmapFont/FontParser.h +++ b/Source/Core/BitmapFont/FontParser.h @@ -0,0 +1,68 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef BITMAPFONTPARSER_H +#define BITMAPFONTPARSER_H + +#include +#include +#include +#include "BM_Font.h" +#include + +namespace Rocket { +namespace Core { +namespace BitmapFont { + +/** + @author Peter Curry + */ + +class FontParser : public BaseXMLParser +{ + public: + FontParser( BM_Font *face ); + virtual ~FontParser(); + + /// Called when the parser finds the beginning of an element tag. + virtual void HandleElementStart(const String& name, const XMLAttributes& attributes); + /// Called when the parser finds the end of an element tag. + virtual void HandleElementEnd(const String& name); + /// Called when the parser encounters data. + virtual void HandleData(const String& data); + + private: + FontParser(); + BM_Font *BM_face; + int char_id; + int kern_id; +}; + +} +} +} +#endif diff --git a/Source/Core/BitmapFont/FontProvider.cpp b/Source/Core/BitmapFont/FontProvider.cpp index 0b4217cdb..4ce670380 100644 --- a/Source/Core/BitmapFont/FontProvider.cpp +++ b/Source/Core/BitmapFont/FontProvider.cpp @@ -30,10 +30,10 @@ #include "../FontFaceHandle.h" #include #include -//#include "../FontFamily.h" +#include "FontFamily.h" #include -//#include "BM_Font.h" -//#include "FontParser.h" +#include "BM_Font.h" +#include "FontParser.h" namespace Rocket { namespace Core { @@ -79,27 +79,27 @@ void FontProvider::Shutdown() // 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); + 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 (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; + 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; -// } + 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; } @@ -107,23 +107,23 @@ bool FontProvider::LoadFontFace(const String& file_name) // 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; -// } + 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; -// } + if (instance->AddFace(bm_font, family, style, weight, true)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); + return false; + } return true; } @@ -175,71 +175,69 @@ bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& // 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; -// } + Rocket::Core::FontFamily* font_family = NULL; + FontFamilyMap::iterator iterator = instance->font_families.find(family); + if (iterator != instance->font_families.end()) + font_family = (*iterator).second; + else + { + font_family = new FontFamily(family); + instance->font_families[family] = font_family; + } -// return font_family->AddFace((BM_Font *) face, style, weight, release_stream); + 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 ); + BM_Font *bm_face = new BM_Font(); + FontParser parser( bm_face ); -// FileInterface* file_interface = GetFileInterface(); -// FileHandle handle = file_interface->Open(file_name); + FileInterface* file_interface = GetFileInterface(); + FileHandle handle = file_interface->Open(file_name); -// if (!handle) -// { -// return NULL; -// } + if (!handle) + { + return NULL; + } -// size_t length = file_interface->Length(handle); + size_t length = file_interface->Length(handle); -// byte* buffer = new byte[length]; -// file_interface->Read(buffer, length, handle); -// file_interface->Close(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 ); + StreamMemory* stream = new StreamMemory( buffer, length ); + stream->SetSourceURL( file_name ); -// parser.Parse( stream ); + parser.Parse( stream ); -// URL file_url = file_name; + URL file_url = file_name; -// bm_face->Face.Source = file_url.GetFileName(); -// bm_face->Face.Directory = file_url.GetPath(); + bm_face->Face.Source = file_url.GetFileName(); + bm_face->Face.Directory = file_url.GetPath(); -// return bm_face; - return 0; + return bm_face; } // Loads a FreeType face from memory. void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data) { -// URL file_url = source + ".fnt"; + 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 ); + 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 ); + parser.Parse( stream ); -// bm_face->Face.Source = file_url.GetFileName(); -// bm_face->Face.Directory = file_url.GetPath(); + bm_face->Face.Source = file_url.GetFileName(); + bm_face->Face.Directory = file_url.GetPath(); -// return bm_face; - return 0; + return bm_face; } } From b6a71b5ec56f1b0ab3919e842a0f8123c0e4c98f Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Sun, 30 Aug 2015 00:00:43 +0200 Subject: [PATCH 05/13] Finally works --- Source/Core/BitmapFont/FontFaceLayer.cpp | 24 ++++++++++++++---------- Source/Core/BitmapFont/FontParser.cpp | 6 +++--- Source/Core/TextureLayoutTexture.cpp | 5 ++++- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Source/Core/BitmapFont/FontFaceLayer.cpp b/Source/Core/BitmapFont/FontFaceLayer.cpp index 92c6a02dd..67ca2fcf2 100644 --- a/Source/Core/BitmapFont/FontFaceLayer.cpp +++ b/Source/Core/BitmapFont/FontFaceLayer.cpp @@ -77,20 +77,16 @@ bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, Font else { // Initialise the texture layout for the glyphs. - unsigned int size = glyphs.size(); - if(size == 0) - { - return false; - } - - characters.resize(glyphs[size - 1].character); - + characters.resize(glyphs.size(), Character()); for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) - { + { const FontGlyph& glyph = *i; + if(glyph.dimensions.x <= 0 || glyph.dimensions.y <= 0) + continue; + Vector2i glyph_origin( glyph.bitmap_dimensions.x, glyph.bitmap_dimensions.y ); // position in texture - Vector2i glyph_dimension = glyph.dimensions; // size of char + Vector2i glyph_dimensions = glyph.dimensions; // size of char Character character; character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y)); @@ -107,8 +103,16 @@ bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, Font characters[glyph.character] = character; + // Add the character's dimensions into the texture layout engine. + texture_layout.AddRectangle(glyph.character, glyph_dimensions); + } + // Generate the texture layout; this will position the glyph rectangles efficiently and + // allocate the texture data ready for writing. + if (!texture_layout.GenerateLayout(512)) + return false; + Texture texture; if (!texture.Load( bm_font_face_handle->GetTextureBaseName() + "_0.tga", bm_font_face_handle->GetTextureDirectory() ) ) return false; diff --git a/Source/Core/BitmapFont/FontParser.cpp b/Source/Core/BitmapFont/FontParser.cpp index b0ecc2594..54a3351e9 100644 --- a/Source/Core/BitmapFont/FontParser.cpp +++ b/Source/Core/BitmapFont/FontParser.cpp @@ -49,11 +49,11 @@ void FontParser::HandleElementStart(const String& name, const XMLAttributes& att { if ( name == "info" ) { - BM_face->Face.FamilyName = "Arial";//attributes.Get( "face" )->Get< String >(); + BM_face->Face.FamilyName = attributes.Get( "face" )->Get< String >(); BM_face->Face.Size = attributes.Get( "size" )->Get< int >(); BM_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; BM_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - BM_face->Face.CharsetName = "";//attributes.Get( "charset" )->Get< String >(); + BM_face->Face.CharsetName = attributes.Get( "charset" )->Get< String >(); BM_face->Face.IsUnicode = attributes.Get( "unicode" )->Get< bool >(); BM_face->Face.StretchHeight = attributes.Get( "stretchH" )->Get< int >(); BM_face->Face.IsSmoothed = attributes.Get( "smooth" )->Get< bool >(); @@ -84,7 +84,7 @@ void FontParser::HandleElementStart(const String& name, const XMLAttributes& att else if ( name == "page" ) { BM_face->PagesInfo[ attributes.Get( "id" )->Get< int >() ].Id = attributes.Get( "id" )->Get< int >(); - BM_face->PagesInfo[ attributes.Get( "id" )->Get< int >() ].FileName = "Arial_0.tga";//attributes.Get( "file" )->Get< String >(); + BM_face->PagesInfo[ attributes.Get( "id" )->Get< int >() ].FileName = attributes.Get( "file" )->Get< String >(); } else if ( name == "chars" ) { diff --git a/Source/Core/TextureLayoutTexture.cpp b/Source/Core/TextureLayoutTexture.cpp index c0b718592..607ce25f1 100644 --- a/Source/Core/TextureLayoutTexture.cpp +++ b/Source/Core/TextureLayoutTexture.cpp @@ -65,7 +65,10 @@ int TextureLayoutTexture::Generate(TextureLayout& layout, int maximum_dimensions if (!rectangle.IsPlaced()) { - square_pixels += (rectangle.GetDimensions().x + 1) * (rectangle.GetDimensions().y + 1); + int x = rectangle.GetDimensions().x + 1; + int y = rectangle.GetDimensions().y + 1; + + square_pixels += x*y; ++unplaced_rectangles; } } From 443bbb5c66f3787d614850b0c54fbb148a7eab5c Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Mon, 31 Aug 2015 00:54:23 +0200 Subject: [PATCH 06/13] Refactor --- Build/cmake/FileList.cmake | 2 +- .../{BM_Font.h => BitmapFontDefinitions.h} | 41 +------------------ Source/Core/BitmapFont/FontFace.cpp | 2 +- Source/Core/BitmapFont/FontFace.h | 6 +-- Source/Core/BitmapFont/FontFaceHandle.cpp | 37 +++++++++-------- Source/Core/BitmapFont/FontFaceHandle.h | 28 ++++++------- Source/Core/BitmapFont/FontFaceLayer.cpp | 22 +++++----- Source/Core/BitmapFont/FontFamily.cpp | 2 +- Source/Core/BitmapFont/FontFamily.h | 2 +- Source/Core/BitmapFont/FontParser.cpp | 28 +------------ Source/Core/BitmapFont/FontParser.h | 6 +-- Source/Core/BitmapFont/FontProvider.cpp | 22 ++++------ 12 files changed, 68 insertions(+), 130 deletions(-) rename Source/Core/BitmapFont/{BM_Font.h => BitmapFontDefinitions.h} (84%) diff --git a/Build/cmake/FileList.cmake b/Build/cmake/FileList.cmake index 5fe33a56d..3fa19cd44 100644 --- a/Build/cmake/FileList.cmake +++ b/Build/cmake/FileList.cmake @@ -41,7 +41,7 @@ set(Core_HDR_FILES ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.h ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.h ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.h - ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/BM_Font.h + ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/BitmapFontDefinitions.h ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontParser.h ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFace.h ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceHandle.h diff --git a/Source/Core/BitmapFont/BM_Font.h b/Source/Core/BitmapFont/BitmapFontDefinitions.h similarity index 84% rename from Source/Core/BitmapFont/BM_Font.h rename to Source/Core/BitmapFont/BitmapFontDefinitions.h index 040d6345a..867ecd2ce 100644 --- a/Source/Core/BitmapFont/BM_Font.h +++ b/Source/Core/BitmapFont/BitmapFontDefinitions.h @@ -37,36 +37,14 @@ 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; + String BitmapSource; 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 @@ -75,22 +53,10 @@ namespace BitmapFont { 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; @@ -101,8 +67,6 @@ namespace BitmapFont { int XOffset; int YOffset; int Advance; - int PageId; - int ChannelUsed; }; struct KerningInfo @@ -112,12 +76,11 @@ namespace BitmapFont { int KerningAmount; }; - class BM_Font + class BitmapFontDefinitions { public: FontInfo Face; CharacterCommonInfo CommonCharactersInfo; - PageInfo *PagesInfo; CharacterInfo *CharactersInfo; KerningInfo *KerningsInfo; diff --git a/Source/Core/BitmapFont/FontFace.cpp b/Source/Core/BitmapFont/FontFace.cpp index df0289694..3ee2f13af 100644 --- a/Source/Core/BitmapFont/FontFace.cpp +++ b/Source/Core/BitmapFont/FontFace.cpp @@ -34,7 +34,7 @@ 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) +FontFace::FontFace(BitmapFontDefinitions *_face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream) { face = _face; } diff --git a/Source/Core/BitmapFont/FontFace.h b/Source/Core/BitmapFont/FontFace.h index 178929622..3f34eadaf 100644 --- a/Source/Core/BitmapFont/FontFace.h +++ b/Source/Core/BitmapFont/FontFace.h @@ -29,7 +29,7 @@ #define ROCKETCOREBITMAPFONTFACE_H #include "../../../Include/Rocket/Core/FontFace.h" -#include "BM_Font.h" +#include "BitmapFontDefinitions.h" namespace Rocket { namespace Core { @@ -44,7 +44,7 @@ class FontFaceHandle; class FontFace : public Rocket::Core::FontFace { public: - FontFace(BM_Font *_face, Font::Style style, Font::Weight weight, bool release_stream); + FontFace(BitmapFontDefinitions *_face, Font::Style style, Font::Weight weight, bool release_stream); ~FontFace(); /// Returns a handle for positioning and rendering this face at the given size. @@ -58,7 +58,7 @@ class FontFace : public Rocket::Core::FontFace void ReleaseFace(); private: - BM_Font *face; + BitmapFontDefinitions *face; }; } diff --git a/Source/Core/BitmapFont/FontFaceHandle.cpp b/Source/Core/BitmapFont/FontFaceHandle.cpp index e887bc1e0..3069746e1 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.cpp +++ b/Source/Core/BitmapFont/FontFaceHandle.cpp @@ -63,16 +63,28 @@ FontFaceHandle::~FontFaceHandle() } // Initialises the handle so it is able to render text. -bool FontFaceHandle::Initialise(BM_Font *bm_face, const String& _charset, int _size) +bool FontFaceHandle::Initialise(BitmapFontDefinitions *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; + TextureWidth = bm_face->CommonCharactersInfo.ScaleWidth; + TextureHeight = bm_face->CommonCharactersInfo.ScaleHeight; raw_charset = _charset; + URL fnt_source = bm_face->Face.Source; + URL bitmap_source = bm_face->Face.BitmapSource; + if(bitmap_source.GetPath().Empty()) + { + TextureSource = fnt_source.GetPath() + bitmap_source.GetFileName(); + if(!bitmap_source.GetExtension().Empty()) + { + TextureSource += "." + bitmap_source.GetExtension(); + } + } + else + { + TextureSource = bitmap_source.GetPathedFileName(); + } + if (!UnicodeRange::BuildList(charset, raw_charset)) { Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString()); @@ -86,13 +98,11 @@ bool FontFaceHandle::Initialise(BM_Font *bm_face, const String& _charset, int _s // 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; } @@ -288,7 +298,7 @@ void FontFaceHandle::OnReferenceDeactivate() delete this; } -void FontFaceHandle::GenerateMetrics(BM_Font *bm_face) +void FontFaceHandle::GenerateMetrics(BitmapFontDefinitions *bm_face) { line_height = bm_face->CommonCharactersInfo.LineHeight; baseline = bm_face->CommonCharactersInfo.BaseLine; @@ -316,7 +326,7 @@ void FontFaceHandle::GenerateMetrics(BM_Font *bm_face) x_height = 0; } -void FontFaceHandle::BuildGlyphMap(BM_Font *bm_face, const UnicodeRange& unicode_range) +void FontFaceHandle::BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range) { glyphs.resize(unicode_range.max_codepoint + 1); @@ -349,11 +359,6 @@ void Rocket::Core::BitmapFont::FontFaceHandle::BuildGlyph(FontGlyph& glyph, Char // 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; @@ -361,7 +366,7 @@ void Rocket::Core::BitmapFont::FontFaceHandle::BuildGlyph(FontGlyph& glyph, Char glyph.bitmap_data = NULL; } -void Rocket::Core::BitmapFont::FontFaceHandle::BuildKerning(BM_Font *bm_face) +void Rocket::Core::BitmapFont::FontFaceHandle::BuildKerning(BitmapFontDefinitions *bm_face) { // Compile the kerning information for this character if the font includes it. // if ( bm_face->CommonCharactersInfo.KerningCount > 0 ) diff --git a/Source/Core/BitmapFont/FontFaceHandle.h b/Source/Core/BitmapFont/FontFaceHandle.h index d56e48cae..9ea30cdb1 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.h +++ b/Source/Core/BitmapFont/FontFaceHandle.h @@ -36,7 +36,7 @@ #include "../../../Include/Rocket/Core/String.h" #include "../../../Include/Rocket/Core/Texture.h" #include "../FontFaceHandle.h" -#include "BM_Font.h" +#include "BitmapFontDefinitions.h" namespace Rocket { namespace Core { @@ -57,7 +57,7 @@ class FontFaceHandle : public Rocket::Core::FontFaceHandle /// @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); + bool Initialise(BitmapFontDefinitions *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. @@ -93,41 +93,41 @@ class FontFaceHandle : public Rocket::Core::FontFaceHandle /// @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 + const String & GetTextureSource() const { - return TextureBaseName; + return TextureSource; } - const String & GetTextureDirectory() const + unsigned int GetTextureWidth() const { - return TextureDirectory; + return TextureWidth; } - int GetTextureSize() const + unsigned int GetTextureHeight() const { - return TextureSize; + return TextureHeight; } - protected: /// Destroys the handle. virtual void OnReferenceDeactivate(); private: - void GenerateMetrics(BM_Font *bm_face); + void GenerateMetrics(BitmapFontDefinitions *bm_face); - void BuildGlyphMap(BM_Font *bm_face, const UnicodeRange& unicode_range); + void BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range); void BuildGlyph(FontGlyph& glyph, CharacterInfo *ft_glyph); - void BuildKerning(BM_Font *bm_face); + void BuildKerning(BitmapFontDefinitions *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 TextureSource; String TextureDirectory; - int TextureSize; + unsigned int TextureWidth; + unsigned int TextureHeight; }; } diff --git a/Source/Core/BitmapFont/FontFaceLayer.cpp b/Source/Core/BitmapFont/FontFaceLayer.cpp index 67ca2fcf2..48c26795c 100644 --- a/Source/Core/BitmapFont/FontFaceLayer.cpp +++ b/Source/Core/BitmapFont/FontFaceLayer.cpp @@ -76,6 +76,13 @@ bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, Font } else { + // Load texture from file + Texture texture; + if (!texture.Load( bm_font_face_handle->GetTextureSource() )) + return false; + + textures.push_back(texture); + // Initialise the texture layout for the glyphs. characters.resize(glyphs.size(), Character()); for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) @@ -96,16 +103,15 @@ bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, Font 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()); + character.texcoords[0].x = float(glyph_origin.x) / float(bm_font_face_handle->GetTextureWidth()); + character.texcoords[0].y = float(glyph_origin.y) / float(bm_font_face_handle->GetTextureHeight()); + character.texcoords[1].x = float(glyph_origin.x + character.dimensions.x) / float(bm_font_face_handle->GetTextureWidth()); + character.texcoords[1].y = float(glyph_origin.y + character.dimensions.y) / float(bm_font_face_handle->GetTextureHeight()); characters[glyph.character] = character; // Add the character's dimensions into the texture layout engine. texture_layout.AddRectangle(glyph.character, glyph_dimensions); - } // Generate the texture layout; this will position the glyph rectangles efficiently and @@ -113,13 +119,7 @@ bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, Font if (!texture_layout.GenerateLayout(512)) return false; - 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; } diff --git a/Source/Core/BitmapFont/FontFamily.cpp b/Source/Core/BitmapFont/FontFamily.cpp index dc1ec7f95..33f6ac33b 100644 --- a/Source/Core/BitmapFont/FontFamily.cpp +++ b/Source/Core/BitmapFont/FontFamily.cpp @@ -44,7 +44,7 @@ FontFamily::~FontFamily() // Adds a new face to the family. bool FontFamily::AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream) { - Rocket::Core::FontFace* face = new FontFace((BM_Font*)bm_face, style, weight, release_stream); + Rocket::Core::FontFace* face = new FontFace((BitmapFontDefinitions*)bm_face, style, weight, release_stream); font_faces.push_back(face); return true; diff --git a/Source/Core/BitmapFont/FontFamily.h b/Source/Core/BitmapFont/FontFamily.h index 9dafc243d..0f14fe511 100644 --- a/Source/Core/BitmapFont/FontFamily.h +++ b/Source/Core/BitmapFont/FontFamily.h @@ -30,7 +30,7 @@ #include "../../../Include/Rocket/Core/Font.h" #include "../../../Include/Rocket/Core/FontFamily.h" -#include "BM_Font.h" +#include "BitmapFontDefinitions.h" namespace Rocket { namespace Core { diff --git a/Source/Core/BitmapFont/FontParser.cpp b/Source/Core/BitmapFont/FontParser.cpp index 54a3351e9..568d06499 100644 --- a/Source/Core/BitmapFont/FontParser.cpp +++ b/Source/Core/BitmapFont/FontParser.cpp @@ -32,7 +32,7 @@ namespace Rocket { namespace Core { namespace BitmapFont { -FontParser::FontParser( BM_Font *face ) +FontParser::FontParser( BitmapFontDefinitions *face ) : BaseXMLParser() { BM_face = face; @@ -53,39 +53,17 @@ void FontParser::HandleElementStart(const String& name, const XMLAttributes& att BM_face->Face.Size = attributes.Get( "size" )->Get< int >(); BM_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; BM_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - BM_face->Face.CharsetName = attributes.Get( "charset" )->Get< String >(); - BM_face->Face.IsUnicode = attributes.Get( "unicode" )->Get< bool >(); - BM_face->Face.StretchHeight = attributes.Get( "stretchH" )->Get< int >(); - BM_face->Face.IsSmoothed = attributes.Get( "smooth" )->Get< bool >(); - BM_face->Face.SuperSamplingLevel = attributes.Get( "aa" )->Get< int >(); - //:TODO: - //BM_face->Face.FamilyName = attributes.Get( "padding" )->Get< String >(); - //BM_face->Face.FamilyName = attributes.Get( "spacing" )->Get< String >(); - BM_face->Face.Outline = attributes.Get( "outline" )->Get< int >(); + BM_face->Face.BitmapSource = attributes.Get( "src" )->Get< String >(); } else if ( name == "common" ) { - BM_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >(); BM_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >(); BM_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >(); BM_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >(); - BM_face->CommonCharactersInfo.PageCount = attributes.Get( "pages" )->Get< int >(); - BM_face->CommonCharactersInfo.IsPacked = attributes.Get( "packed" )->Get< bool >(); - BM_face->CommonCharactersInfo.AlphaChanelUsage = attributes.Get( "alphaChnl" )->Get< int >(); - BM_face->CommonCharactersInfo.RedChanelUsage = attributes.Get( "redChnl" )->Get< int >(); - BM_face->CommonCharactersInfo.GreenChanelUsage = attributes.Get( "greenChnl" )->Get< int >(); - BM_face->CommonCharactersInfo.BlueChanelUsage = attributes.Get( "blueChnl" )->Get< int >(); - - BM_face->PagesInfo = new PageInfo[BM_face->CommonCharactersInfo.PageCount]; BM_face->CommonCharactersInfo.CharacterCount = 0; BM_face->CommonCharactersInfo.KerningCount = 0; } - else if ( name == "page" ) - { - BM_face->PagesInfo[ attributes.Get( "id" )->Get< int >() ].Id = attributes.Get( "id" )->Get< int >(); - BM_face->PagesInfo[ attributes.Get( "id" )->Get< int >() ].FileName = attributes.Get( "file" )->Get< String >(); - } else if ( name == "chars" ) { BM_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >(); @@ -101,8 +79,6 @@ void FontParser::HandleElementStart(const String& name, const XMLAttributes& att BM_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >(); BM_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >(); BM_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >(); - BM_face->CharactersInfo[ char_id ].PageId = attributes.Get( "page" )->Get< int >(); - BM_face->CharactersInfo[ char_id ].ChannelUsed = attributes.Get( "chnl" )->Get< int >(); char_id++; } diff --git a/Source/Core/BitmapFont/FontParser.h b/Source/Core/BitmapFont/FontParser.h index b426d6396..59316540c 100644 --- a/Source/Core/BitmapFont/FontParser.h +++ b/Source/Core/BitmapFont/FontParser.h @@ -31,7 +31,7 @@ #include #include #include -#include "BM_Font.h" +#include "BitmapFontDefinitions.h" #include namespace Rocket { @@ -45,7 +45,7 @@ namespace BitmapFont { class FontParser : public BaseXMLParser { public: - FontParser( BM_Font *face ); + FontParser( BitmapFontDefinitions *face ); virtual ~FontParser(); /// Called when the parser finds the beginning of an element tag. @@ -57,7 +57,7 @@ class FontParser : public BaseXMLParser private: FontParser(); - BM_Font *BM_face; + BitmapFontDefinitions *BM_face; int char_id; int kern_id; }; diff --git a/Source/Core/BitmapFont/FontProvider.cpp b/Source/Core/BitmapFont/FontProvider.cpp index 4ce670380..1832fc117 100644 --- a/Source/Core/BitmapFont/FontProvider.cpp +++ b/Source/Core/BitmapFont/FontProvider.cpp @@ -32,7 +32,7 @@ #include #include "FontFamily.h" #include -#include "BM_Font.h" +#include "BitmapFontDefinitions.h" #include "FontParser.h" namespace Rocket { @@ -79,7 +79,7 @@ void FontProvider::Shutdown() // 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); + BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name); if (bm_font == NULL) { @@ -107,7 +107,7 @@ bool FontProvider::LoadFontFace(const String& file_name) // 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); + BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name); if (bm_font == NULL) { Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); @@ -185,14 +185,14 @@ bool FontProvider::AddFace(void* face, const String& family, Font::Style style, instance->font_families[family] = font_family; } - return font_family->AddFace((BM_Font *) face, style, weight, release_stream); + return font_family->AddFace((BitmapFontDefinitions *) 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(); + BitmapFontDefinitions *bm_face = new BitmapFontDefinitions(); FontParser parser( bm_face ); FileInterface* file_interface = GetFileInterface(); @@ -214,11 +214,7 @@ void* FontProvider::LoadFace(const String& file_name) parser.Parse( stream ); - URL file_url = file_name; - - bm_face->Face.Source = file_url.GetFileName(); - bm_face->Face.Directory = file_url.GetPath(); - + bm_face->Face.Source = file_name; return bm_face; } @@ -227,16 +223,14 @@ void* FontProvider::LoadFace(const byte* data, int data_length, const String& so { URL file_url = source + ".fnt"; - BM_Font *bm_face = new BM_Font(); + BitmapFontDefinitions *bm_face = new BitmapFontDefinitions(); FontParser parser( bm_face ); StreamMemory* stream = new StreamMemory( data, data_length ); stream->SetSourceURL( file_url ); parser.Parse( stream ); - bm_face->Face.Source = file_url.GetFileName(); - bm_face->Face.Directory = file_url.GetPath(); - + bm_face->Face.Source = file_url.GetPathedFileName(); return bm_face; } From 589b15b8ee4617132f081995b8d0a5702a555e7c Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Mon, 31 Aug 2015 01:24:08 +0200 Subject: [PATCH 07/13] Fixes --- Source/Core/BitmapFont/FontFaceHandle.cpp | 40 ++++------------------- Source/Core/BitmapFont/FontFaceHandle.h | 5 ++- 2 files changed, 8 insertions(+), 37 deletions(-) diff --git a/Source/Core/BitmapFont/FontFaceHandle.cpp b/Source/Core/BitmapFont/FontFaceHandle.cpp index 3069746e1..9bb2800da 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.cpp +++ b/Source/Core/BitmapFont/FontFaceHandle.cpp @@ -65,11 +65,13 @@ FontFaceHandle::~FontFaceHandle() // Initialises the handle so it is able to render text. bool FontFaceHandle::Initialise(BitmapFontDefinitions *bm_face, const String& _charset, int _size) { + this->bm_face = bm_face; size = _size; TextureWidth = bm_face->CommonCharactersInfo.ScaleWidth; TextureHeight = bm_face->CommonCharactersInfo.ScaleHeight; raw_charset = _charset; + // Construct proper path to texture URL fnt_source = bm_face->Face.Source; URL bitmap_source = bm_face->Face.BitmapSource; if(bitmap_source.GetPath().Empty()) @@ -366,46 +368,16 @@ void Rocket::Core::BitmapFont::FontFaceHandle::BuildGlyph(FontGlyph& glyph, Char glyph.bitmap_data = NULL; } -void Rocket::Core::BitmapFont::FontFaceHandle::BuildKerning(BitmapFontDefinitions *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) -// { -// GlyphKerningList& glyph_kerning = kerning.insert(FontKerningList::value_type(rhs, GlyphKerningList())).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; + if( bm_face != NULL) + { + return bm_face->BM_Helper_GetXKerning(lhs, rhs); + } -// return lhs_iterator->second; return 0; } - // Generates (or shares) a layer derived from a font effect. Rocket::Core::FontFaceLayer* FontFaceHandle::GenerateLayer( FontEffect* font_effect) { diff --git a/Source/Core/BitmapFont/FontFaceHandle.h b/Source/Core/BitmapFont/FontFaceHandle.h index 9ea30cdb1..e637ca3c8 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.h +++ b/Source/Core/BitmapFont/FontFaceHandle.h @@ -57,7 +57,7 @@ class FontFaceHandle : public Rocket::Core::FontFaceHandle /// @param[in] charset The comma-separated list of unicode ranges this handle must support. /// @param[in] size The size, in points, of the face this handle should render at. /// @return True if the handle initialised successfully and is ready for rendering, false if an error occured. - bool Initialise(BitmapFontDefinitions *ft_face, const String& charset, int size); + bool Initialise(BitmapFontDefinitions *bm_face, const String& charset, int size); /// Returns the width a string will take up if rendered with this handle. /// @param[in] string The string to measure. @@ -117,13 +117,12 @@ class FontFaceHandle : public Rocket::Core::FontFaceHandle void BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range); void BuildGlyph(FontGlyph& glyph, CharacterInfo *ft_glyph); - - void BuildKerning(BitmapFontDefinitions *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); + BitmapFontDefinitions * bm_face; String TextureSource; String TextureDirectory; unsigned int TextureWidth; From 281206cc7e27307d8419dbe5e021c290b8d8f4eb Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Mon, 31 Aug 2015 01:27:22 +0200 Subject: [PATCH 08/13] Sample fix --- Samples/assets/Arial.fnt | 389 +++++++++++++++++++-------------------- 1 file changed, 193 insertions(+), 196 deletions(-) diff --git a/Samples/assets/Arial.fnt b/Samples/assets/Arial.fnt index 0a01381f8..4513a62d4 100644 --- a/Samples/assets/Arial.fnt +++ b/Samples/assets/Arial.fnt @@ -1,202 +1,199 @@ - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From dc37832b9c416e950161d59738fcf07971be0206 Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Thu, 3 Sep 2015 17:45:29 +0200 Subject: [PATCH 09/13] Working events --- Source/Core/BitmapFont/FontFaceHandle.cpp | 19 ++++---- Source/Core/BitmapFont/FontFaceHandle.h | 14 +++--- Source/Core/BitmapFont/FontFaceLayer.cpp | 13 ++---- Source/Core/BitmapFont/FontParser.cpp | 54 +++++++++++------------ Source/Core/BitmapFont/FontParser.h | 2 +- Source/Core/BitmapFont/FontProvider.cpp | 37 ++-------------- 6 files changed, 50 insertions(+), 89 deletions(-) diff --git a/Source/Core/BitmapFont/FontFaceHandle.cpp b/Source/Core/BitmapFont/FontFaceHandle.cpp index 9bb2800da..1ebe93cc3 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.cpp +++ b/Source/Core/BitmapFont/FontFaceHandle.cpp @@ -67,8 +67,9 @@ bool FontFaceHandle::Initialise(BitmapFontDefinitions *bm_face, const String& _c { this->bm_face = bm_face; size = _size; - TextureWidth = bm_face->CommonCharactersInfo.ScaleWidth; - TextureHeight = bm_face->CommonCharactersInfo.ScaleHeight; + line_height = _size; + texture_width = bm_face->CommonCharactersInfo.ScaleWidth; + texture_height = bm_face->CommonCharactersInfo.ScaleHeight; raw_charset = _charset; // Construct proper path to texture @@ -76,15 +77,15 @@ bool FontFaceHandle::Initialise(BitmapFontDefinitions *bm_face, const String& _c URL bitmap_source = bm_face->Face.BitmapSource; if(bitmap_source.GetPath().Empty()) { - TextureSource = fnt_source.GetPath() + bitmap_source.GetFileName(); + texture_source = fnt_source.GetPath() + bitmap_source.GetFileName(); if(!bitmap_source.GetExtension().Empty()) { - TextureSource += "." + bitmap_source.GetExtension(); + texture_source += "." + bitmap_source.GetExtension(); } } else { - TextureSource = bitmap_source.GetPathedFileName(); + texture_source = bitmap_source.GetPathedFileName(); } if (!UnicodeRange::BuildList(charset, raw_charset)) @@ -305,12 +306,10 @@ void FontFaceHandle::GenerateMetrics(BitmapFontDefinitions *bm_face) line_height = bm_face->CommonCharactersInfo.LineHeight; baseline = bm_face->CommonCharactersInfo.BaseLine; - underline_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine;//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_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine; + baseline += int( underline_position / 1.6f ); underline_thickness = 1.0f; + average_advance = 0; for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i) average_advance += i->advance; diff --git a/Source/Core/BitmapFont/FontFaceHandle.h b/Source/Core/BitmapFont/FontFaceHandle.h index e637ca3c8..554331ff0 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.h +++ b/Source/Core/BitmapFont/FontFaceHandle.h @@ -95,17 +95,17 @@ class FontFaceHandle : public Rocket::Core::FontFaceHandle const String & GetTextureSource() const { - return TextureSource; + return texture_source; } unsigned int GetTextureWidth() const { - return TextureWidth; + return texture_width; } unsigned int GetTextureHeight() const { - return TextureHeight; + return texture_height; } protected: @@ -123,10 +123,10 @@ class FontFaceHandle : public Rocket::Core::FontFaceHandle virtual FontFaceLayer* GenerateLayer(FontEffect* font_effect); BitmapFontDefinitions * bm_face; - String TextureSource; - String TextureDirectory; - unsigned int TextureWidth; - unsigned int TextureHeight; + String texture_source; + String texture_directory; + unsigned int texture_width; + unsigned int texture_height; }; } diff --git a/Source/Core/BitmapFont/FontFaceLayer.cpp b/Source/Core/BitmapFont/FontFaceLayer.cpp index 48c26795c..dc3136efc 100644 --- a/Source/Core/BitmapFont/FontFaceLayer.cpp +++ b/Source/Core/BitmapFont/FontFaceLayer.cpp @@ -41,27 +41,20 @@ FontFaceLayer::FontFaceLayer() : Rocket::Core::FontFaceLayer() 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) { + (void)(_effect); + 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. @@ -96,7 +89,7 @@ bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, Font Vector2i glyph_dimensions = glyph.dimensions; // size of char Character character; - character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y)); + character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y) - handle->GetBaseline()*3 ); character.dimensions = Vector2f((float) glyph.dimensions.x, (float) glyph.dimensions.y); // Set the character's texture index. diff --git a/Source/Core/BitmapFont/FontParser.cpp b/Source/Core/BitmapFont/FontParser.cpp index 568d06499..3ddff1c9a 100644 --- a/Source/Core/BitmapFont/FontParser.cpp +++ b/Source/Core/BitmapFont/FontParser.cpp @@ -35,7 +35,7 @@ namespace BitmapFont { FontParser::FontParser( BitmapFontDefinitions *face ) : BaseXMLParser() { - BM_face = face; + bm_face = face; char_id = 0; kern_id = 0; } @@ -49,49 +49,49 @@ void FontParser::HandleElementStart(const String& name, const XMLAttributes& att { if ( name == "info" ) { - BM_face->Face.FamilyName = attributes.Get( "face" )->Get< String >(); - BM_face->Face.Size = attributes.Get( "size" )->Get< int >(); - BM_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; - BM_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - BM_face->Face.BitmapSource = attributes.Get( "src" )->Get< String >(); + bm_face->Face.FamilyName = attributes.Get( "face" )->Get< String >(); + bm_face->Face.Size = attributes.Get( "size" )->Get< int >(); + bm_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; + bm_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; + bm_face->Face.BitmapSource = attributes.Get( "src" )->Get< String >(); } else if ( name == "common" ) { - BM_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >(); - BM_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >(); - BM_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >(); - BM_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >(); - BM_face->CommonCharactersInfo.CharacterCount = 0; - BM_face->CommonCharactersInfo.KerningCount = 0; + bm_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >(); + bm_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >() * -1; + bm_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >(); + bm_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >(); + bm_face->CommonCharactersInfo.CharacterCount = 0; + bm_face->CommonCharactersInfo.KerningCount = 0; } else if ( name == "chars" ) { - BM_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >(); - BM_face->CharactersInfo = new CharacterInfo[ attributes.Get( "count" )->Get< int >() ]; + bm_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >(); + bm_face->CharactersInfo = new CharacterInfo[ attributes.Get( "count" )->Get< int >() ]; } else if ( name == "char" ) { - BM_face->CharactersInfo[ char_id ].Id = attributes.Get( "id" )->Get< int >(); - BM_face->CharactersInfo[ char_id ].X = attributes.Get( "x" )->Get< int >(); //The left position of the character image in the texture. - BM_face->CharactersInfo[ char_id ].Y = attributes.Get( "y" )->Get< int >(); //The top position of the character image in the texture. - BM_face->CharactersInfo[ char_id ].Width = attributes.Get( "width" )->Get< int >(); //The width of the character image in the texture. - BM_face->CharactersInfo[ char_id ].Height = attributes.Get( "height" )->Get< int >(); //The height of the character image in the texture. - BM_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >(); - BM_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >(); - BM_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >(); + bm_face->CharactersInfo[ char_id ].Id = attributes.Get( "id" )->Get< int >(); + bm_face->CharactersInfo[ char_id ].X = attributes.Get( "x" )->Get< int >(); //The left position of the character image in the texture. + bm_face->CharactersInfo[ char_id ].Y = attributes.Get( "y" )->Get< int >(); //The top position of the character image in the texture. + bm_face->CharactersInfo[ char_id ].Width = attributes.Get( "width" )->Get< int >(); //The width of the character image in the texture. + bm_face->CharactersInfo[ char_id ].Height = attributes.Get( "height" )->Get< int >(); //The height of the character image in the texture. + bm_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >(); + bm_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >(); + bm_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >(); char_id++; } else if ( name == "kernings" ) { - BM_face->CommonCharactersInfo.KerningCount = attributes.Get( "count" )->Get< int >(); - BM_face->KerningsInfo = new KerningInfo[ attributes.Get( "count" )->Get< int >() ]; + bm_face->CommonCharactersInfo.KerningCount = attributes.Get( "count" )->Get< int >(); + bm_face->KerningsInfo = new KerningInfo[ attributes.Get( "count" )->Get< int >() ]; } else if ( name == "kerning" ) { - BM_face->KerningsInfo[ kern_id ].FirstCharacterId = attributes.Get( "first" )->Get< int >(); - BM_face->KerningsInfo[ kern_id ].SecondCharacterId = attributes.Get( "second" )->Get< int >(); - BM_face->KerningsInfo[ kern_id ].KerningAmount = attributes.Get( "amount" )->Get< int >(); + bm_face->KerningsInfo[ kern_id ].FirstCharacterId = attributes.Get( "first" )->Get< int >(); + bm_face->KerningsInfo[ kern_id ].SecondCharacterId = attributes.Get( "second" )->Get< int >(); + bm_face->KerningsInfo[ kern_id ].KerningAmount = attributes.Get( "amount" )->Get< int >(); kern_id++; } diff --git a/Source/Core/BitmapFont/FontParser.h b/Source/Core/BitmapFont/FontParser.h index 59316540c..b91497018 100644 --- a/Source/Core/BitmapFont/FontParser.h +++ b/Source/Core/BitmapFont/FontParser.h @@ -57,7 +57,7 @@ class FontParser : public BaseXMLParser private: FontParser(); - BitmapFontDefinitions *BM_face; + BitmapFontDefinitions *bm_face; int char_id; int kern_id; }; diff --git a/Source/Core/BitmapFont/FontProvider.cpp b/Source/Core/BitmapFont/FontProvider.cpp index 1832fc117..b582fe9e7 100644 --- a/Source/Core/BitmapFont/FontProvider.cpp +++ b/Source/Core/BitmapFont/FontProvider.cpp @@ -130,46 +130,15 @@ bool FontProvider::LoadFontFace(const String& file_name, const String& family, F 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; - // } + // TODO: Loading from memory return false; } // Adds a new font face to the database, loading from memory. bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight) { -// 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; -// } + // TODO Loading from memory + return false; } // Adds a loaded face to the appropriate font family. From fabcfe40976cbfcc04386f173bde41f5242abff1 Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Thu, 3 Sep 2015 18:34:48 +0200 Subject: [PATCH 10/13] Bitmap font example --- Build/CMakeLists.txt | 4 +- Build/cmake/SampleFileList.cmake | 7 ++ Samples/assets/Arial.fnt | 2 +- Samples/assets/bitmapfont.rml | 28 ++++++ Samples/basic/bitmapfont/src/main.cpp | 130 ++++++++++++++++++++++++++ 5 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 Samples/assets/bitmapfont.rml create mode 100644 Samples/basic/bitmapfont/src/main.cpp diff --git a/Build/CMakeLists.txt b/Build/CMakeLists.txt index edacf9e48..1fce0fb5f 100644 --- a/Build/CMakeLists.txt +++ b/Build/CMakeLists.txt @@ -141,7 +141,7 @@ if(APPLE) option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF) endif() -option(BUILD_SAMPLES "Build samples" OFF) +option(BUILD_SAMPLES "Build samples" ON) if(WIN32) option(SKIP_DIRECTX_SAMPLES "Skip build of all DirectX related samples. Only applies if BUILD_SAMPLES is ON" OFF) option(SKIP_DIRECTX9_SAMPLE "Skip build of DirectX 9 related sample. Only applies if BUILD_SAMPLES is ON and SKIP_DIRECTX_SAMPLES is OFF" OFF) @@ -457,7 +457,7 @@ endmacro() if(BUILD_SAMPLES) include(SampleFileList) - set(samples treeview customlog drag loaddocument) + set(samples treeview customlog drag loaddocument bitmapfont) set(tutorials template datagrid datagrid_tree tutorial_drag) if(NOT BUILD_FRAMEWORK) diff --git a/Build/cmake/SampleFileList.cmake b/Build/cmake/SampleFileList.cmake index 3a174bc5f..535b397ed 100644 --- a/Build/cmake/SampleFileList.cmake +++ b/Build/cmake/SampleFileList.cmake @@ -45,6 +45,13 @@ set(loaddocument_SRC_FILES ${PROJECT_SOURCE_DIR}/Samples/basic/loaddocument/src/main.cpp ) +set(bitmapfont_HDR_FILES +) + +set(bitmapfont_SRC_FILES + ${PROJECT_SOURCE_DIR}/Samples/basic/bitmapfont/src/main.cpp +) + set(ogre3d_HDR_FILES ${PROJECT_SOURCE_DIR}/Samples/basic/ogre3d/src/RenderInterfaceOgre3D.h ${PROJECT_SOURCE_DIR}/Samples/basic/ogre3d/src/RocketApplication.h diff --git a/Samples/assets/Arial.fnt b/Samples/assets/Arial.fnt index 4513a62d4..09fd9a70d 100644 --- a/Samples/assets/Arial.fnt +++ b/Samples/assets/Arial.fnt @@ -1,7 +1,7 @@ - + diff --git a/Samples/assets/bitmapfont.rml b/Samples/assets/bitmapfont.rml new file mode 100644 index 000000000..ff53cf0ef --- /dev/null +++ b/Samples/assets/bitmapfont.rml @@ -0,0 +1,28 @@ + + + Demo + + + + + This is a bitmap font
sample. + +
diff --git a/Samples/basic/bitmapfont/src/main.cpp b/Samples/basic/bitmapfont/src/main.cpp new file mode 100644 index 000000000..d919faae9 --- /dev/null +++ b/Samples/basic/bitmapfont/src/main.cpp @@ -0,0 +1,130 @@ +/* + * This source file is part of libRocket, the HTML/CSS Interface Middleware + * + * For the latest information, see http://www.librocket.com + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include +#include +#include +#include + +Rocket::Core::Context* context = NULL; + +ShellRenderInterfaceExtensions *shell_renderer; + +void GameLoop() +{ + context->Update(); + + shell_renderer->PrepareRenderBuffer(); + context->Render(); + shell_renderer->PresentRenderBuffer(); +} + +#if defined ROCKET_PLATFORM_WIN32 +#include +int APIENTRY WinMain(HINSTANCE ROCKET_UNUSED_PARAMETER(instance_handle), HINSTANCE ROCKET_UNUSED_PARAMETER(previous_instance_handle), char* ROCKET_UNUSED_PARAMETER(command_line), int ROCKET_UNUSED_PARAMETER(command_show)) +#else +int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)) +#endif +{ +#ifdef ROCKET_PLATFORM_WIN32 + ROCKET_UNUSED(instance_handle); + ROCKET_UNUSED(previous_instance_handle); + ROCKET_UNUSED(command_line); + ROCKET_UNUSED(command_show); +#else + ROCKET_UNUSED(argc); + ROCKET_UNUSED(argv); +#endif + +#ifdef ROCKET_PLATFORM_LINUX +#define APP_PATH "../Samples/basic/loaddocument/" +#else +#define APP_PATH "../../Samples/basic/loaddocument/" +#endif + +#ifdef ROCKET_PLATFORM_WIN32 + DoAllocConsole(); +#endif + + int window_width = 1024; + int window_height = 768; + + ShellRenderInterfaceOpenGL opengl_renderer; + shell_renderer = &opengl_renderer; + + // Generic OS initialisation, creates a window and attaches OpenGL. + if (!Shell::Initialise(APP_PATH) || + !Shell::OpenWindow("Load Document Sample", shell_renderer, window_width, window_height, true)) + { + Shell::Shutdown(); + return -1; + } + + // Rocket initialisation. + Rocket::Core::SetRenderInterface(&opengl_renderer); + shell_renderer->SetViewport(window_width, window_height); + + ShellSystemInterface system_interface; + Rocket::Core::SetSystemInterface(&system_interface); + + Rocket::Core::Initialise(); + + // Create the main Rocket context and set it on the shell's input layer. + context = Rocket::Core::CreateContext("main", Rocket::Core::Vector2i(window_width, window_height)); + if (context == NULL) + { + Rocket::Core::Shutdown(); + Shell::Shutdown(); + return -1; + } + + Rocket::Debugger::Initialise(context); + Input::SetContext(context); + shell_renderer->SetContext(context); + + // Load bitmap font + Rocket::Core::FontDatabase::LoadFontFace("../../assets/Arial.fnt"); + + // Load and show the demo document. + Rocket::Core::ElementDocument* document = context->LoadDocument("../../assets/bitmapfont.rml"); + if (document != NULL) + { + document->Show(); + document->RemoveReference(); + } + + Shell::EventLoop(GameLoop); + + // Shutdown Rocket. + context->RemoveReference(); + Rocket::Core::Shutdown(); + + Shell::CloseWindow(); + Shell::Shutdown(); + + return 0; +} From 96ff48d53bb6504848458901a591123cfa207798 Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Thu, 3 Sep 2015 18:55:58 +0200 Subject: [PATCH 11/13] tabs instead of spaces --- .../Core/BitmapFont/BitmapFontDefinitions.h | 186 ++--- Source/Core/BitmapFont/FontFace.cpp | 146 ++-- Source/Core/BitmapFont/FontFace.h | 24 +- Source/Core/BitmapFont/FontFaceHandle.cpp | 574 ++++++++-------- Source/Core/BitmapFont/FontFaceHandle.h | 144 ++-- Source/Core/BitmapFont/FontFaceLayer.cpp | 108 +-- Source/Core/BitmapFont/FontFaceLayer.h | 38 +- Source/Core/BitmapFont/FontFamily.cpp | 6 +- Source/Core/BitmapFont/FontFamily.h | 20 +- Source/Core/BitmapFont/FontParser.cpp | 100 +-- Source/Core/BitmapFont/FontParser.h | 30 +- Source/Core/BitmapFont/FontProvider.cpp | 198 +++--- Source/Core/FontFaceHandle.cpp | 18 - Source/Core/FontFaceHandle.h | 32 +- Source/Core/FontFaceLayer.h | 4 +- Source/Core/FontProvider.cpp | 8 +- Source/Core/FreeType/FontFace.cpp | 160 ++--- Source/Core/FreeType/FontFace.h | 24 +- Source/Core/FreeType/FontFaceHandle.cpp | 640 +++++++++--------- Source/Core/FreeType/FontFaceHandle.h | 98 +-- Source/Core/FreeType/FontFamily.cpp | 6 +- Source/Core/FreeType/FontFamily.h | 20 +- Source/Core/FreeType/FontProvider.cpp | 312 ++++----- 23 files changed, 1439 insertions(+), 1457 deletions(-) diff --git a/Source/Core/BitmapFont/BitmapFontDefinitions.h b/Source/Core/BitmapFont/BitmapFontDefinitions.h index 867ecd2ce..afdcef15c 100644 --- a/Source/Core/BitmapFont/BitmapFontDefinitions.h +++ b/Source/Core/BitmapFont/BitmapFontDefinitions.h @@ -37,109 +37,109 @@ namespace Rocket { namespace Core { namespace BitmapFont { - struct FontInfo - { - String FamilyName; - String Source; - String BitmapSource; - int Size; - Font::Style Style; - Font::Weight Weight; - }; + struct FontInfo + { + String FamilyName; + String Source; + String BitmapSource; + int Size; + Font::Style Style; + Font::Weight Weight; + }; - struct CharacterCommonInfo - { - int LineHeight; - int BaseLine; - int ScaleWidth; - int ScaleHeight; - int CharacterCount; - int KerningCount; - }; + struct CharacterCommonInfo + { + int LineHeight; + int BaseLine; + int ScaleWidth; + int ScaleHeight; + int CharacterCount; + int KerningCount; + }; - struct CharacterInfo - { - int Id; - int X; - int Y; - int Width; - int Height; - int XOffset; - int YOffset; - int Advance; - }; + struct CharacterInfo + { + int Id; + int X; + int Y; + int Width; + int Height; + int XOffset; + int YOffset; + int Advance; + }; - struct KerningInfo - { - int FirstCharacterId; - int SecondCharacterId; - int KerningAmount; - }; + struct KerningInfo + { + int FirstCharacterId; + int SecondCharacterId; + int KerningAmount; + }; - class BitmapFontDefinitions - { - public: - FontInfo Face; - CharacterCommonInfo CommonCharactersInfo; - CharacterInfo *CharactersInfo; - KerningInfo *KerningsInfo; + class BitmapFontDefinitions + { + public: + FontInfo Face; + CharacterCommonInfo CommonCharactersInfo; + CharacterInfo *CharactersInfo; + KerningInfo *KerningsInfo; - int BM_Helper_GetCharacterTableIndex( int unicode_code ) - { - return BinarySearch( unicode_code, 0, CommonCharactersInfo.CharacterCount ); - } + int BM_Helper_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; - } - } + 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; - } + return 0; + } - private: + 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; + 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 ); - } - } - } - }; + 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 ); + } + } + } + }; } } diff --git a/Source/Core/BitmapFont/FontFace.cpp b/Source/Core/BitmapFont/FontFace.cpp index 3ee2f13af..e8c4505ae 100644 --- a/Source/Core/BitmapFont/FontFace.cpp +++ b/Source/Core/BitmapFont/FontFace.cpp @@ -36,93 +36,93 @@ namespace BitmapFont { FontFace::FontFace(BitmapFontDefinitions *_face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream) { - face = _face; + face = _face; } FontFace::~FontFace() { - ReleaseFace(); + 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; + UnicodeRangeList charset; + + HandleMap::iterator iterator = handles.find(size); + if (iterator != handles.end()) + { + const HandleList& handles = (*iterator).second; + + // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same + // string). + String raw_charset(_raw_charset); + for (size_t i = 0; i < handles.size(); ++i) + { + if (handles[i]->GetRawCharset() == _raw_charset) + { + handles[i]->AddReference(); + return (FontFaceHandle*)handles[i]; + } + } + + // Check all the handles if their charsets contain the requested charset. + if (!UnicodeRange::BuildList(charset, raw_charset)) + { + Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); + return NULL; + } + + for (size_t i = 0; i < handles.size(); ++i) + { + bool range_contained = true; + + const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); + for (size_t j = 0; j < charset.size() && range_contained; ++j) + { + if (!charset[j].IsContained(handle_charset)) + range_contained = false; + } + + if (range_contained) + { + handles[i]->AddReference(); + return (FontFaceHandle*)handles[i]; + } + } + } + + // See if this face has been released. + if (face == NULL) + { + Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); + return NULL; + } + + // Construct and initialise the new handle. + FontFaceHandle* handle = new FontFaceHandle(); + if (!handle->Initialise(face, _raw_charset, size)) + { + handle->RemoveReference(); + return NULL; + } + + // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face + // releases it. + if (iterator != handles.end()) + (*iterator).second.push_back(handle); + else + handles[size] = HandleList(1, handle); + + handle->AddReference(); + + return handle; } // Releases the face's structure. void FontFace::ReleaseFace() { - delete face; + delete face; } } diff --git a/Source/Core/BitmapFont/FontFace.h b/Source/Core/BitmapFont/FontFace.h index 3f34eadaf..17f1bc07e 100644 --- a/Source/Core/BitmapFont/FontFace.h +++ b/Source/Core/BitmapFont/FontFace.h @@ -38,27 +38,27 @@ namespace BitmapFont { class FontFaceHandle; /** - @author Peter Curry + @author Peter Curry */ class FontFace : public Rocket::Core::FontFace { public: - FontFace(BitmapFontDefinitions *_face, Font::Style style, Font::Weight weight, bool release_stream); - ~FontFace(); + FontFace(BitmapFontDefinitions *_face, Font::Style style, Font::Weight weight, bool release_stream); + ~FontFace(); - /// Returns a handle for positioning and rendering this face at the given size. - /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. - /// @param[in] size The size of the desired handle, in points. - /// @return The shared font handle. - Rocket::Core::FontFaceHandle* GetHandle(const String& charset, int size); + /// 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(); + /// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed, + /// but existing ones can still be fetched. + void ReleaseFace(); private: - BitmapFontDefinitions *face; + BitmapFontDefinitions *face; }; } diff --git a/Source/Core/BitmapFont/FontFaceHandle.cpp b/Source/Core/BitmapFont/FontFaceHandle.cpp index 1ebe93cc3..0f59ffd77 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.cpp +++ b/Source/Core/BitmapFont/FontFaceHandle.cpp @@ -38,24 +38,24 @@ namespace BitmapFont { class FontEffectSort { public: - bool operator()(const Rocket::Core::FontEffect* lhs, const Rocket::Core::FontEffect* rhs) - { - return lhs->GetZIndex() < rhs->GetZIndex(); - } + 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; + size = 0; + average_advance = 0; + x_height = 0; + line_height = 0; + baseline = 0; - underline_position = 0; - underline_thickness = 0; + underline_position = 0; + underline_thickness = 0; - base_layer = NULL; + base_layer = NULL; } FontFaceHandle::~FontFaceHandle() @@ -65,362 +65,362 @@ FontFaceHandle::~FontFaceHandle() // Initialises the handle so it is able to render text. bool FontFaceHandle::Initialise(BitmapFontDefinitions *bm_face, const String& _charset, int _size) { - this->bm_face = bm_face; - size = _size; - line_height = _size; - texture_width = bm_face->CommonCharactersInfo.ScaleWidth; - texture_height = bm_face->CommonCharactersInfo.ScaleHeight; - raw_charset = _charset; - - // Construct proper path to texture - URL fnt_source = bm_face->Face.Source; - URL bitmap_source = bm_face->Face.BitmapSource; - if(bitmap_source.GetPath().Empty()) - { - texture_source = fnt_source.GetPath() + bitmap_source.GetFileName(); - if(!bitmap_source.GetExtension().Empty()) - { - texture_source += "." + bitmap_source.GetExtension(); - } - } - else - { - texture_source = bitmap_source.GetPathedFileName(); - } - - if (!UnicodeRange::BuildList(charset, raw_charset)) - { - Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString()); - return false; - } - - // Construct the list of the characters specified by the charset. - for (size_t i = 0; i < charset.size(); ++i) - BuildGlyphMap(bm_face, charset[i]); - - // Generate the metrics for the handle. - GenerateMetrics(bm_face); - - // Generate the default layer and layer configuration. - base_layer = GenerateLayer(NULL); - layer_configurations.push_back(LayerConfiguration()); - layer_configurations.back().push_back(base_layer); - - return true; + this->bm_face = bm_face; + size = _size; + line_height = _size; + texture_width = bm_face->CommonCharactersInfo.ScaleWidth; + texture_height = bm_face->CommonCharactersInfo.ScaleHeight; + raw_charset = _charset; + + // Construct proper path to texture + URL fnt_source = bm_face->Face.Source; + URL bitmap_source = bm_face->Face.BitmapSource; + if(bitmap_source.GetPath().Empty()) + { + texture_source = fnt_source.GetPath() + bitmap_source.GetFileName(); + if(!bitmap_source.GetExtension().Empty()) + { + texture_source += "." + bitmap_source.GetExtension(); + } + } + else + { + texture_source = bitmap_source.GetPathedFileName(); + } + + if (!UnicodeRange::BuildList(charset, raw_charset)) + { + Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString()); + return false; + } + + // Construct the list of the characters specified by the charset. + for (size_t i = 0; i < charset.size(); ++i) + BuildGlyphMap(bm_face, charset[i]); + + // Generate the metrics for the handle. + GenerateMetrics(bm_face); + + // Generate the default layer and layer configuration. + base_layer = GenerateLayer(NULL); + layer_configurations.push_back(LayerConfiguration()); + layer_configurations.back().push_back(base_layer); + + return true; } // Returns the width a string will take up if rendered with this handle. int FontFaceHandle::GetStringWidth(const WString& string, word prior_character) const { - int width = 0; + int width = 0; - for (size_t i = 0; i < string.Length(); i++) - { - word character_code = string[i]; + 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]; + 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; + // 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; - } + prior_character = character_code; + } - return width; + 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); + 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; + 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); + 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; + int geometry_index = 0; + int line_width = 0; - ROCKET_ASSERT(layer_configuration_index >= 0); - ROCKET_ASSERT(layer_configuration_index < (int) layer_configurations.size()); + 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]; + // 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(); + 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()); + // 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)); + // 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; + line_width = 0; + word prior_character = 0; - const word* string_iterator = string.CString(); - const word* string_end = string.CString() + string.Length(); + 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]; + 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); + // 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); + layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour); - line_width += glyph.advance; - prior_character = *string_iterator; - } + line_width += glyph.advance; + prior_character = *string_iterator; + } - geometry_index += layer->GetNumTextures(); - } + geometry_index += layer->GetNumTextures(); + } - // Cull any excess geometry from a previous generation. - geometry.resize(geometry_index); + // Cull any excess geometry from a previous generation. + geometry.resize(geometry_index); - return line_width; + 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); + 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; + delete this; } void FontFaceHandle::GenerateMetrics(BitmapFontDefinitions *bm_face) { - line_height = bm_face->CommonCharactersInfo.LineHeight; - baseline = bm_face->CommonCharactersInfo.BaseLine; + line_height = bm_face->CommonCharactersInfo.LineHeight; + baseline = bm_face->CommonCharactersInfo.BaseLine; - underline_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine; - baseline += int( underline_position / 1.6f ); - underline_thickness = 1.0f; + underline_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine; + baseline += int( underline_position / 1.6f ); + underline_thickness = 1.0f; - average_advance = 0; - for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i) - average_advance += i->advance; + 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)); + // 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); + // 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; + if ( index >= 0) + x_height = bm_face->CharactersInfo[ index ].Height; + else + x_height = 0; } void FontFaceHandle::BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range) { - glyphs.resize(unicode_range.max_codepoint + 1); - - for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code) - { - int index = bm_face->BM_Helper_GetCharacterTableIndex( character_code ); - - if ( index < 0 ) - { - continue; - } - - FontGlyph glyph; - glyph.character = character_code; - BuildGlyph(glyph, &bm_face->CharactersInfo[ index ] ); - glyphs[character_code] = glyph; - } + glyphs.resize(unicode_range.max_codepoint + 1); + + for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code) + { + int index = bm_face->BM_Helper_GetCharacterTableIndex( character_code ); + + if ( index < 0 ) + { + continue; + } + + FontGlyph glyph; + glyph.character = character_code; + BuildGlyph(glyph, &bm_face->CharactersInfo[ index ] ); + glyphs[character_code] = glyph; + } } void Rocket::Core::BitmapFont::FontFaceHandle::BuildGlyph(FontGlyph& glyph, CharacterInfo *bm_glyph) { - // Set the glyph's dimensions. - glyph.dimensions.x = bm_glyph->Width; - glyph.dimensions.y = bm_glyph->Height; + // Set the glyph's 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 bearing. + glyph.bearing.x = bm_glyph->XOffset; + glyph.bearing.y = bm_glyph->YOffset; - // Set the glyph's advance. - glyph.advance = bm_glyph->Advance; + // Set the glyph's advance. + glyph.advance = bm_glyph->Advance; - // Set the glyph's bitmap position. - glyph.bitmap_dimensions.x = bm_glyph->X; - glyph.bitmap_dimensions.y = bm_glyph->Y; + // Set the glyph's bitmap position. + glyph.bitmap_dimensions.x = bm_glyph->X; + glyph.bitmap_dimensions.y = bm_glyph->Y; - glyph.bitmap_data = NULL; + glyph.bitmap_data = NULL; } int Rocket::Core::BitmapFont::FontFaceHandle::GetKerning(word lhs, word rhs) const { - if( bm_face != NULL) - { - return bm_face->BM_Helper_GetXKerning(lhs, rhs); - } + if( bm_face != NULL) + { + return bm_face->BM_Helper_GetXKerning(lhs, rhs); + } - return 0; + 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; + // 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; } } diff --git a/Source/Core/BitmapFont/FontFaceHandle.h b/Source/Core/BitmapFont/FontFaceHandle.h index 554331ff0..d2bc86985 100644 --- a/Source/Core/BitmapFont/FontFaceHandle.h +++ b/Source/Core/BitmapFont/FontFaceHandle.h @@ -43,90 +43,90 @@ namespace Core { namespace BitmapFont { /** - @author Peter Curry + @author Peter Curry */ class FontFaceHandle : public Rocket::Core::FontFaceHandle { public: - FontFaceHandle(); - virtual ~FontFaceHandle(); - - /// Initialises the handle so it is able to render text. - /// @param[in] ft_face The FreeType face that this handle is rendering. - /// @param[in] charset The comma-separated list of unicode ranges this handle must support. - /// @param[in] size The size, in points, of the face this handle should render at. - /// @return True if the handle initialised successfully and is ready for rendering, false if an error occured. - bool Initialise(BitmapFontDefinitions *bm_face, const String& charset, int size); - - /// Returns the width a string will take up if rendered with this handle. - /// @param[in] string The string to measure. - /// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning. - /// @return The width, in pixels, this string will occupy if rendered with this handle. - int GetStringWidth(const WString& string, word prior_character = 0) const; - - /// Generates, if required, the layer configuration for a given array of font effects. - /// @param[in] font_effects The list of font effects to generate the configuration for. - /// @return The index to use when generating geometry using this configuration. - int GenerateLayerConfiguration(Rocket::Core::FontEffectMap& font_effects); - - /// Generates the texture data for a layer (for the texture database). - /// @param[out] texture_data The pointer to be set to the generated texture data. - /// @param[out] texture_dimensions The dimensions of the texture. - /// @param[in] layer_id The id of the layer to request the texture data from. - /// @param[in] texture_id The index of the texture within the layer to generate. - bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id); - - /// Generates the geometry required to render a single line of text. - /// @param[out] geometry An array of geometries to generate the geometry into. - /// @param[in] string The string to render. - /// @param[in] position The position of the baseline of the first character to render. - /// @param[in] colour The colour to render the text. - /// @return The width, in pixels, of the string geometry. - int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const; - - /// Generates the geometry required to render a line above, below or through a line of text. - /// @param[out] geometry The geometry to append the newly created geometry into. - /// @param[in] position The position of the baseline of the lined text. - /// @param[in] width The width of the string to line. - /// @param[in] height The height to render the line at. - /// @param[in] colour The colour to draw the line in. - void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const; - - const String & GetTextureSource() const - { - return texture_source; - } - - unsigned int GetTextureWidth() const - { - return texture_width; - } - - unsigned int GetTextureHeight() const - { - return texture_height; - } + FontFaceHandle(); + virtual ~FontFaceHandle(); + + /// Initialises the handle so it is able to render text. + /// @param[in] ft_face The FreeType face that this handle is rendering. + /// @param[in] charset The comma-separated list of unicode ranges this handle must support. + /// @param[in] size The size, in points, of the face this handle should render at. + /// @return True if the handle initialised successfully and is ready for rendering, false if an error occured. + bool Initialise(BitmapFontDefinitions *bm_face, const String& charset, int size); + + /// Returns the width a string will take up if rendered with this handle. + /// @param[in] string The string to measure. + /// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning. + /// @return The width, in pixels, this string will occupy if rendered with this handle. + int GetStringWidth(const WString& string, word prior_character = 0) const; + + /// Generates, if required, the layer configuration for a given array of font effects. + /// @param[in] font_effects The list of font effects to generate the configuration for. + /// @return The index to use when generating geometry using this configuration. + int GenerateLayerConfiguration(Rocket::Core::FontEffectMap& font_effects); + + /// Generates the texture data for a layer (for the texture database). + /// @param[out] texture_data The pointer to be set to the generated texture data. + /// @param[out] texture_dimensions The dimensions of the texture. + /// @param[in] layer_id The id of the layer to request the texture data from. + /// @param[in] texture_id The index of the texture within the layer to generate. + bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id); + + /// Generates the geometry required to render a single line of text. + /// @param[out] geometry An array of geometries to generate the geometry into. + /// @param[in] string The string to render. + /// @param[in] position The position of the baseline of the first character to render. + /// @param[in] colour The colour to render the text. + /// @return The width, in pixels, of the string geometry. + int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const; + + /// Generates the geometry required to render a line above, below or through a line of text. + /// @param[out] geometry The geometry to append the newly created geometry into. + /// @param[in] position The position of the baseline of the lined text. + /// @param[in] width The width of the string to line. + /// @param[in] height The height to render the line at. + /// @param[in] colour The colour to draw the line in. + void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const; + + const String & GetTextureSource() const + { + return texture_source; + } + + unsigned int GetTextureWidth() const + { + return texture_width; + } + + unsigned int GetTextureHeight() const + { + return texture_height; + } protected: - /// Destroys the handle. - virtual void OnReferenceDeactivate(); + /// Destroys the handle. + virtual void OnReferenceDeactivate(); private: - void GenerateMetrics(BitmapFontDefinitions *bm_face); + void GenerateMetrics(BitmapFontDefinitions *bm_face); - void BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range); - void BuildGlyph(FontGlyph& glyph, CharacterInfo *ft_glyph); - int GetKerning(word lhs, word rhs) const; + void BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range); + void BuildGlyph(FontGlyph& glyph, CharacterInfo *ft_glyph); + int GetKerning(word lhs, word rhs) const; - // Generates (or shares) a layer derived from a font effect. - virtual FontFaceLayer* GenerateLayer(FontEffect* font_effect); + // Generates (or shares) a layer derived from a font effect. + virtual FontFaceLayer* GenerateLayer(FontEffect* font_effect); - BitmapFontDefinitions * bm_face; - String texture_source; - String texture_directory; - unsigned int texture_width; - unsigned int texture_height; + BitmapFontDefinitions * bm_face; + String texture_source; + String texture_directory; + unsigned int texture_width; + unsigned int texture_height; }; } diff --git a/Source/Core/BitmapFont/FontFaceLayer.cpp b/Source/Core/BitmapFont/FontFaceLayer.cpp index dc3136efc..635c26e19 100644 --- a/Source/Core/BitmapFont/FontFaceLayer.cpp +++ b/Source/Core/BitmapFont/FontFaceLayer.cpp @@ -35,8 +35,8 @@ namespace BitmapFont { FontFaceLayer::FontFaceLayer() : Rocket::Core::FontFaceLayer() { - handle = NULL; - effect = NULL; + handle = NULL; + effect = NULL; } FontFaceLayer::~FontFaceLayer() @@ -46,80 +46,80 @@ FontFaceLayer::~FontFaceLayer() // Generates the character and texture data for the layer. bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, FontEffect* _effect, const Rocket::Core::FontFaceLayer* clone, bool deep_clone) { - (void)(_effect); + (void)(_effect); - Rocket::Core::BitmapFont::FontFaceHandle - * bm_font_face_handle; + Rocket::Core::BitmapFont::FontFaceHandle + * bm_font_face_handle; - handle = _handle; + handle = _handle; - bm_font_face_handle = ( Rocket::Core::BitmapFont::FontFaceHandle * ) handle; + bm_font_face_handle = ( Rocket::Core::BitmapFont::FontFaceHandle * ) handle; - const FontGlyphList& glyphs = handle->GetGlyphs(); + 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; + // Clone the geometry and textures from the clone layer. + if (clone != NULL) + { + // Copy the cloned layer's characters. + characters = clone->characters; - // Copy (and reference) the cloned layer's textures. - for (size_t i = 0; i < clone->textures.size(); ++i) - textures.push_back(clone->textures[i]); - } - else - { - // Load texture from file - Texture texture; - if (!texture.Load( bm_font_face_handle->GetTextureSource() )) - return false; + // Copy (and reference) the cloned layer's textures. + for (size_t i = 0; i < clone->textures.size(); ++i) + textures.push_back(clone->textures[i]); + } + else + { + // Load texture from file + Texture texture; + if (!texture.Load( bm_font_face_handle->GetTextureSource() )) + return false; - textures.push_back(texture); + textures.push_back(texture); - // Initialise the texture layout for the glyphs. - characters.resize(glyphs.size(), Character()); - for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) - { - const FontGlyph& glyph = *i; + // Initialise the texture layout for the glyphs. + characters.resize(glyphs.size(), Character()); + for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) + { + const FontGlyph& glyph = *i; - if(glyph.dimensions.x <= 0 || glyph.dimensions.y <= 0) - continue; + if(glyph.dimensions.x <= 0 || glyph.dimensions.y <= 0) + continue; - Vector2i glyph_origin( glyph.bitmap_dimensions.x, glyph.bitmap_dimensions.y ); // position in texture - Vector2i glyph_dimensions = glyph.dimensions; // size of char + Vector2i glyph_origin( glyph.bitmap_dimensions.x, glyph.bitmap_dimensions.y ); // position in texture + Vector2i glyph_dimensions = glyph.dimensions; // size of char - Character character; - character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y) - handle->GetBaseline()*3 ); - character.dimensions = Vector2f((float) glyph.dimensions.x, (float) glyph.dimensions.y); + Character character; + character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y) - handle->GetBaseline()*3 ); + character.dimensions = Vector2f((float) glyph.dimensions.x, (float) glyph.dimensions.y); - // Set the character's texture index. - character.texture_index = 0; + // Set the character's texture index. + character.texture_index = 0; - // Generate the character's texture coordinates. - character.texcoords[0].x = float(glyph_origin.x) / float(bm_font_face_handle->GetTextureWidth()); - character.texcoords[0].y = float(glyph_origin.y) / float(bm_font_face_handle->GetTextureHeight()); - character.texcoords[1].x = float(glyph_origin.x + character.dimensions.x) / float(bm_font_face_handle->GetTextureWidth()); - character.texcoords[1].y = float(glyph_origin.y + character.dimensions.y) / float(bm_font_face_handle->GetTextureHeight()); + // Generate the character's texture coordinates. + character.texcoords[0].x = float(glyph_origin.x) / float(bm_font_face_handle->GetTextureWidth()); + character.texcoords[0].y = float(glyph_origin.y) / float(bm_font_face_handle->GetTextureHeight()); + character.texcoords[1].x = float(glyph_origin.x + character.dimensions.x) / float(bm_font_face_handle->GetTextureWidth()); + character.texcoords[1].y = float(glyph_origin.y + character.dimensions.y) / float(bm_font_face_handle->GetTextureHeight()); - characters[glyph.character] = character; + characters[glyph.character] = character; - // Add the character's dimensions into the texture layout engine. - texture_layout.AddRectangle(glyph.character, glyph_dimensions); - } + // Add the character's dimensions into the texture layout engine. + texture_layout.AddRectangle(glyph.character, glyph_dimensions); + } - // Generate the texture layout; this will position the glyph rectangles efficiently and - // allocate the texture data ready for writing. - if (!texture_layout.GenerateLayout(512)) - return false; + // Generate the texture layout; this will position the glyph rectangles efficiently and + // allocate the texture data ready for writing. + if (!texture_layout.GenerateLayout(512)) + return false; - } - return true; + } + 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; + return true; } } diff --git a/Source/Core/BitmapFont/FontFaceLayer.h b/Source/Core/BitmapFont/FontFaceLayer.h index 6adcaa2a1..dff03e39d 100644 --- a/Source/Core/BitmapFont/FontFaceLayer.h +++ b/Source/Core/BitmapFont/FontFaceLayer.h @@ -38,36 +38,36 @@ namespace Rocket { namespace Core { - class TextureLayout; + 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 + 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(); + 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 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); + /// 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); }; diff --git a/Source/Core/BitmapFont/FontFamily.cpp b/Source/Core/BitmapFont/FontFamily.cpp index 33f6ac33b..29c5e6b2b 100644 --- a/Source/Core/BitmapFont/FontFamily.cpp +++ b/Source/Core/BitmapFont/FontFamily.cpp @@ -44,10 +44,10 @@ FontFamily::~FontFamily() // Adds a new face to the family. bool FontFamily::AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream) { - Rocket::Core::FontFace* face = new FontFace((BitmapFontDefinitions*)bm_face, style, weight, release_stream); - font_faces.push_back(face); + Rocket::Core::FontFace* face = new FontFace((BitmapFontDefinitions*)bm_face, style, weight, release_stream); + font_faces.push_back(face); - return true; + return true; } } diff --git a/Source/Core/BitmapFont/FontFamily.h b/Source/Core/BitmapFont/FontFamily.h index 0f14fe511..9c7b92b7b 100644 --- a/Source/Core/BitmapFont/FontFamily.h +++ b/Source/Core/BitmapFont/FontFamily.h @@ -41,22 +41,22 @@ class FontFaceHandle; namespace BitmapFont { /** - @author Peter Curry + @author Peter Curry */ class FontFamily : public Rocket::Core::FontFamily { public: - FontFamily(const String& name); - ~FontFamily(); + FontFamily(const String& name); + ~FontFamily(); - /// Adds a new face to the family. - /// @param[in] ft_face The previously loaded FreeType face. - /// @param[in] style The style of the new face. - /// @param[in] weight The weight of the new face. - /// @param[in] release_stream True if the application must free the face's memory stream. - /// @return True if the face was loaded successfully, false otherwise. - bool AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream); + /// Adds a new face to the family. + /// @param[in] ft_face The previously loaded FreeType face. + /// @param[in] style The style of the new face. + /// @param[in] weight The weight of the new face. + /// @param[in] release_stream True if the application must free the face's memory stream. + /// @return True if the face was loaded successfully, false otherwise. + bool AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream); }; } diff --git a/Source/Core/BitmapFont/FontParser.cpp b/Source/Core/BitmapFont/FontParser.cpp index 3ddff1c9a..679f68dcf 100644 --- a/Source/Core/BitmapFont/FontParser.cpp +++ b/Source/Core/BitmapFont/FontParser.cpp @@ -33,11 +33,11 @@ namespace Core { namespace BitmapFont { FontParser::FontParser( BitmapFontDefinitions *face ) - : BaseXMLParser() + : BaseXMLParser() { - bm_face = face; - char_id = 0; - kern_id = 0; + bm_face = face; + char_id = 0; + kern_id = 0; } FontParser::~FontParser() @@ -47,54 +47,54 @@ FontParser::~FontParser() // Called when the parser finds the beginning of an element tag. void FontParser::HandleElementStart(const String& name, const XMLAttributes& attributes) { - if ( name == "info" ) - { - bm_face->Face.FamilyName = attributes.Get( "face" )->Get< String >(); - bm_face->Face.Size = attributes.Get( "size" )->Get< int >(); - bm_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; - bm_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - bm_face->Face.BitmapSource = attributes.Get( "src" )->Get< String >(); - } - else if ( name == "common" ) - { - bm_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >(); - bm_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >() * -1; - bm_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >(); - bm_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >(); - bm_face->CommonCharactersInfo.CharacterCount = 0; - bm_face->CommonCharactersInfo.KerningCount = 0; - } - else if ( name == "chars" ) - { - bm_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >(); - bm_face->CharactersInfo = new CharacterInfo[ attributes.Get( "count" )->Get< int >() ]; - } - else if ( name == "char" ) - { - bm_face->CharactersInfo[ char_id ].Id = attributes.Get( "id" )->Get< int >(); - bm_face->CharactersInfo[ char_id ].X = attributes.Get( "x" )->Get< int >(); //The left position of the character image in the texture. - bm_face->CharactersInfo[ char_id ].Y = attributes.Get( "y" )->Get< int >(); //The top position of the character image in the texture. - bm_face->CharactersInfo[ char_id ].Width = attributes.Get( "width" )->Get< int >(); //The width of the character image in the texture. - bm_face->CharactersInfo[ char_id ].Height = attributes.Get( "height" )->Get< int >(); //The height of the character image in the texture. - bm_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >(); - bm_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >(); - bm_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >(); + if ( name == "info" ) + { + bm_face->Face.FamilyName = attributes.Get( "face" )->Get< String >(); + bm_face->Face.Size = attributes.Get( "size" )->Get< int >(); + bm_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; + bm_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; + bm_face->Face.BitmapSource = attributes.Get( "src" )->Get< String >(); + } + else if ( name == "common" ) + { + bm_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >(); + bm_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >() * -1; + bm_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >(); + bm_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >(); + bm_face->CommonCharactersInfo.CharacterCount = 0; + bm_face->CommonCharactersInfo.KerningCount = 0; + } + else if ( name == "chars" ) + { + bm_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >(); + bm_face->CharactersInfo = new CharacterInfo[ attributes.Get( "count" )->Get< int >() ]; + } + else if ( name == "char" ) + { + bm_face->CharactersInfo[ char_id ].Id = attributes.Get( "id" )->Get< int >(); + bm_face->CharactersInfo[ char_id ].X = attributes.Get( "x" )->Get< int >(); //The left position of the character image in the texture. + bm_face->CharactersInfo[ char_id ].Y = attributes.Get( "y" )->Get< int >(); //The top position of the character image in the texture. + bm_face->CharactersInfo[ char_id ].Width = attributes.Get( "width" )->Get< int >(); //The width of the character image in the texture. + bm_face->CharactersInfo[ char_id ].Height = attributes.Get( "height" )->Get< int >(); //The height of the character image in the texture. + bm_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >(); + bm_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >(); + bm_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >(); - char_id++; - } - else if ( name == "kernings" ) - { - bm_face->CommonCharactersInfo.KerningCount = attributes.Get( "count" )->Get< int >(); - bm_face->KerningsInfo = new KerningInfo[ attributes.Get( "count" )->Get< int >() ]; - } - else if ( name == "kerning" ) - { - bm_face->KerningsInfo[ kern_id ].FirstCharacterId = attributes.Get( "first" )->Get< int >(); - bm_face->KerningsInfo[ kern_id ].SecondCharacterId = attributes.Get( "second" )->Get< int >(); - bm_face->KerningsInfo[ kern_id ].KerningAmount = attributes.Get( "amount" )->Get< int >(); + char_id++; + } + else if ( name == "kernings" ) + { + bm_face->CommonCharactersInfo.KerningCount = attributes.Get( "count" )->Get< int >(); + bm_face->KerningsInfo = new KerningInfo[ attributes.Get( "count" )->Get< int >() ]; + } + else if ( name == "kerning" ) + { + bm_face->KerningsInfo[ kern_id ].FirstCharacterId = attributes.Get( "first" )->Get< int >(); + bm_face->KerningsInfo[ kern_id ].SecondCharacterId = attributes.Get( "second" )->Get< int >(); + bm_face->KerningsInfo[ kern_id ].KerningAmount = attributes.Get( "amount" )->Get< int >(); - kern_id++; - } + kern_id++; + } } // Called when the parser finds the end of an element tag. diff --git a/Source/Core/BitmapFont/FontParser.h b/Source/Core/BitmapFont/FontParser.h index b91497018..a8dd1aabd 100644 --- a/Source/Core/BitmapFont/FontParser.h +++ b/Source/Core/BitmapFont/FontParser.h @@ -39,27 +39,27 @@ namespace Core { namespace BitmapFont { /** - @author Peter Curry + @author Peter Curry */ class FontParser : public BaseXMLParser { - public: - FontParser( BitmapFontDefinitions *face ); - virtual ~FontParser(); + public: + FontParser( BitmapFontDefinitions *face ); + virtual ~FontParser(); - /// Called when the parser finds the beginning of an element tag. - virtual void HandleElementStart(const String& name, const XMLAttributes& attributes); - /// Called when the parser finds the end of an element tag. - virtual void HandleElementEnd(const String& name); - /// Called when the parser encounters data. - virtual void HandleData(const String& data); + /// Called when the parser finds the beginning of an element tag. + virtual void HandleElementStart(const String& name, const XMLAttributes& attributes); + /// Called when the parser finds the end of an element tag. + virtual void HandleElementEnd(const String& name); + /// Called when the parser encounters data. + virtual void HandleData(const String& data); - private: - FontParser(); - BitmapFontDefinitions *bm_face; - int char_id; - int kern_id; + private: + FontParser(); + BitmapFontDefinitions *bm_face; + int char_id; + int kern_id; }; } diff --git a/Source/Core/BitmapFont/FontProvider.cpp b/Source/Core/BitmapFont/FontProvider.cpp index b582fe9e7..5d3434f74 100644 --- a/Source/Core/BitmapFont/FontProvider.cpp +++ b/Source/Core/BitmapFont/FontProvider.cpp @@ -44,163 +44,163 @@ FontProvider* FontProvider::instance = NULL; FontProvider::FontProvider() { - ROCKET_ASSERT(instance == NULL); - instance = this; + ROCKET_ASSERT(instance == NULL); + instance = this; } FontProvider::~FontProvider() { - ROCKET_ASSERT(instance == this); - instance = NULL; + ROCKET_ASSERT(instance == this); + instance = NULL; } bool FontProvider::Initialise() { - if (instance == NULL) - { - new FontProvider(); + if (instance == NULL) + { + new FontProvider(); - FontDatabase::AddFontProvider(instance); - } + FontDatabase::AddFontProvider(instance); + } - return true; + return true; } void FontProvider::Shutdown() { - if (instance != NULL) - { - FontDatabase::RemoveFontProvider(instance); - delete instance; - instance = NULL; - } + if (instance != NULL) + { + FontDatabase::RemoveFontProvider(instance); + delete instance; + instance = NULL; + } } // Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself. bool FontProvider::LoadFontFace(const String& file_name) { - BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name); - - if (bm_font == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); - return false; - } - - Font::Style style = bm_font->Face.Style; - Font::Weight weight = bm_font->Face.Weight; - - if (instance->AddFace(bm_font, bm_font->Face.FamilyName, style, weight, true)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); - return false; - } - - return true; + BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name); + + if (bm_font == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); + return false; + } + + Font::Style style = bm_font->Face.Style; + Font::Weight weight = bm_font->Face.Weight; + + if (instance->AddFace(bm_font, bm_font->Face.FamilyName, style, weight, true)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); + return false; + } + + return true; } // Loads a new font face. bool FontProvider::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight) { - BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name); - if (bm_font == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); - return false; - } - - if (instance->AddFace(bm_font, family, style, weight, true)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); - return false; - } - - return true; + BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name); + if (bm_font == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); + return false; + } + + if (instance->AddFace(bm_font, family, style, weight, true)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString()); + return false; + } + + return true; } bool FontProvider::LoadFontFace(const byte* data, int data_length) { - // TODO: Loading from memory - return false; + // TODO: Loading from memory + return false; } // Adds a new font face to the database, loading from memory. bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight) { - // TODO Loading from memory - return false; + // TODO Loading from memory + return false; } // Adds a loaded face to the appropriate font family. bool FontProvider::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream) { - Rocket::Core::FontFamily* font_family = NULL; - FontFamilyMap::iterator iterator = instance->font_families.find(family); - if (iterator != instance->font_families.end()) - font_family = (*iterator).second; - else - { - font_family = new FontFamily(family); - instance->font_families[family] = font_family; - } - - return font_family->AddFace((BitmapFontDefinitions *) face, style, weight, release_stream); - return true; + Rocket::Core::FontFamily* font_family = NULL; + FontFamilyMap::iterator iterator = instance->font_families.find(family); + if (iterator != instance->font_families.end()) + font_family = (*iterator).second; + else + { + font_family = new FontFamily(family); + instance->font_families[family] = font_family; + } + + return font_family->AddFace((BitmapFontDefinitions *) face, style, weight, release_stream); + return true; } // Loads a FreeType face. void* FontProvider::LoadFace(const String& file_name) { - BitmapFontDefinitions *bm_face = new BitmapFontDefinitions(); - FontParser parser( bm_face ); + BitmapFontDefinitions *bm_face = new BitmapFontDefinitions(); + FontParser parser( bm_face ); - FileInterface* file_interface = GetFileInterface(); - FileHandle handle = file_interface->Open(file_name); + FileInterface* file_interface = GetFileInterface(); + FileHandle handle = file_interface->Open(file_name); - if (!handle) - { - return NULL; - } + if (!handle) + { + return NULL; + } - size_t length = file_interface->Length(handle); + size_t length = file_interface->Length(handle); - byte* buffer = new byte[length]; - file_interface->Read(buffer, length, handle); - file_interface->Close(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 ); + StreamMemory* stream = new StreamMemory( buffer, length ); + stream->SetSourceURL( file_name ); - parser.Parse( stream ); + parser.Parse( stream ); - bm_face->Face.Source = file_name; - return bm_face; + bm_face->Face.Source = file_name; + return bm_face; } // Loads a FreeType face from memory. void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data) { - URL file_url = source + ".fnt"; + URL file_url = source + ".fnt"; - BitmapFontDefinitions *bm_face = new BitmapFontDefinitions(); - FontParser parser( bm_face ); - StreamMemory* stream = new StreamMemory( data, data_length ); - stream->SetSourceURL( file_url ); + BitmapFontDefinitions *bm_face = new BitmapFontDefinitions(); + FontParser parser( bm_face ); + StreamMemory* stream = new StreamMemory( data, data_length ); + stream->SetSourceURL( file_url ); - parser.Parse( stream ); + parser.Parse( stream ); - bm_face->Face.Source = file_url.GetPathedFileName(); - return bm_face; + bm_face->Face.Source = file_url.GetPathedFileName(); + return bm_face; } } diff --git a/Source/Core/FontFaceHandle.cpp b/Source/Core/FontFaceHandle.cpp index 8d524a171..d947619e4 100644 --- a/Source/Core/FontFaceHandle.cpp +++ b/Source/Core/FontFaceHandle.cpp @@ -307,24 +307,6 @@ void FontFaceHandle::OnReferenceDeactivate() delete this; } -int FontFaceHandle::GetKerning(word lhs, word rhs) const -{ - /*if(rhs >= kerning.size()) - return 0; - - FontKerningList::const_iterator rhs_iterator = kerning.find(rhs); - if (rhs_iterator == kerning.end()) - return 0; - - GlyphKerningList::const_iterator lhs_iterator = rhs_iterator->find(lhs); - if (lhs_iterator == (*rhs_iterator).end()) - return 0; - - return *lhs_iterator;*/ - - return 0; -} - // Generates (or shares) a layer derived from a font effect. FontFaceLayer* FontFaceHandle::GenerateLayer(FontEffect* font_effect) { diff --git a/Source/Core/FontFaceHandle.h b/Source/Core/FontFaceHandle.h index d1ad9f451..fb19ad9dc 100644 --- a/Source/Core/FontFaceHandle.h +++ b/Source/Core/FontFaceHandle.h @@ -54,42 +54,42 @@ class FontFaceHandle : public ReferenceCountable /// 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. - virtual int GetStringWidth(const WString& string, word prior_character = 0) const = 0; + 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. - virtual int GenerateLayerConfiguration(FontEffectMap& font_effects) = 0; + 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. - virtual bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id) = 0; + 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. @@ -97,33 +97,33 @@ class FontFaceHandle : public ReferenceCountable /// @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. - virtual int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const = 0; + 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. - virtual void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const = 0; + 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(); - FontFaceLayer* GenerateLayer(FontEffect* font_effect); - virtual int GetKerning(word lhs, word rhs) const; + FontFaceLayer* GenerateLayer(FontEffect* font_effect); + virtual int GetKerning(word lhs, word rhs) const = 0; typedef std::vector< int > GlyphKerningList; typedef std::vector< GlyphKerningList > FontKerningList; FontGlyphList glyphs; - FontKerningList kerning; + FontKerningList kerning; typedef std::map< const FontEffect*, FontFaceLayer* > FontLayerMap; typedef std::map< String, FontFaceLayer* > FontLayerCache; diff --git a/Source/Core/FontFaceLayer.h b/Source/Core/FontFaceLayer.h index d45cbfbf7..ab9695b91 100644 --- a/Source/Core/FontFaceLayer.h +++ b/Source/Core/FontFaceLayer.h @@ -60,14 +60,14 @@ class FontFaceLayer /// @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 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. - virtual 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. diff --git a/Source/Core/FontProvider.cpp b/Source/Core/FontProvider.cpp index 99fffd145..41ef12e0e 100644 --- a/Source/Core/FontProvider.cpp +++ b/Source/Core/FontProvider.cpp @@ -34,11 +34,11 @@ namespace Core { // Returns a handle to a font face that can be used to position and render text. Rocket::Core::FontFaceHandle* FontProvider::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size) { - FontFamilyMap::iterator iterator = font_families.find(family); - if (iterator == font_families.end()) - return NULL; + FontFamilyMap::iterator iterator = font_families.find(family); + if (iterator == font_families.end()) + return NULL; - return (*iterator).second->GetFaceHandle(charset, style, weight, size); + return (*iterator).second->GetFaceHandle(charset, style, weight, size); } } diff --git a/Source/Core/FreeType/FontFace.cpp b/Source/Core/FreeType/FontFace.cpp index bc49424a6..b0b366367 100644 --- a/Source/Core/FreeType/FontFace.cpp +++ b/Source/Core/FreeType/FontFace.cpp @@ -36,102 +36,102 @@ namespace FreeType { FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream) { - face = _face; + face = _face; } FontFace::~FontFace() { - ReleaseFace(); + ReleaseFace(); } // Returns a handle for positioning and rendering this face at the given size. Rocket::Core::FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size) { - UnicodeRangeList charset; - - HandleMap::iterator iterator = handles.find(size); - if (iterator != handles.end()) - { - const HandleList& handles = (*iterator).second; - - // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same - // string). - String raw_charset(_raw_charset); - for (size_t i = 0; i < handles.size(); ++i) - { - if (handles[i]->GetRawCharset() == _raw_charset) - { - handles[i]->AddReference(); - return (Rocket::Core::FreeType::FontFaceHandle*)handles[i]; - } - } - - // Check all the handles if their charsets contain the requested charset. - if (!UnicodeRange::BuildList(charset, raw_charset)) - { - Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); - return NULL; - } - - for (size_t i = 0; i < handles.size(); ++i) - { - bool range_contained = true; - - const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); - for (size_t j = 0; j < charset.size() && range_contained; ++j) - { - if (!charset[j].IsContained(handle_charset)) - range_contained = false; - } - - if (range_contained) - { - handles[i]->AddReference(); - return (Rocket::Core::FreeType::FontFaceHandle*)handles[i]; - } - } - } - - // See if this face has been released. - if (face == NULL) - { - Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); - return NULL; - } - - // Construct and initialise the new handle. - FontFaceHandle* handle = new FontFaceHandle(); - if (!handle->Initialise(face, _raw_charset, size)) - { - handle->RemoveReference(); - return NULL; - } - - // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face - // releases it. - if (iterator != handles.end()) - (*iterator).second.push_back(handle); - else - handles[size] = HandleList(1, handle); - - handle->AddReference(); - - return handle; + UnicodeRangeList charset; + + HandleMap::iterator iterator = handles.find(size); + if (iterator != handles.end()) + { + const HandleList& handles = (*iterator).second; + + // Check all the handles if their charsets match the requested one exactly (ie, were specified by the same + // string). + String raw_charset(_raw_charset); + for (size_t i = 0; i < handles.size(); ++i) + { + if (handles[i]->GetRawCharset() == _raw_charset) + { + handles[i]->AddReference(); + return (Rocket::Core::FreeType::FontFaceHandle*)handles[i]; + } + } + + // Check all the handles if their charsets contain the requested charset. + if (!UnicodeRange::BuildList(charset, raw_charset)) + { + Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString()); + return NULL; + } + + for (size_t i = 0; i < handles.size(); ++i) + { + bool range_contained = true; + + const UnicodeRangeList& handle_charset = handles[i]->GetCharset(); + for (size_t j = 0; j < charset.size() && range_contained; ++j) + { + if (!charset[j].IsContained(handle_charset)) + range_contained = false; + } + + if (range_contained) + { + handles[i]->AddReference(); + return (Rocket::Core::FreeType::FontFaceHandle*)handles[i]; + } + } + } + + // See if this face has been released. + if (face == NULL) + { + Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle."); + return NULL; + } + + // Construct and initialise the new handle. + FontFaceHandle* handle = new FontFaceHandle(); + if (!handle->Initialise(face, _raw_charset, size)) + { + handle->RemoveReference(); + return NULL; + } + + // Save the handle, and add a reference for the callee. The initial reference will be removed when the font face + // releases it. + if (iterator != handles.end()) + (*iterator).second.push_back(handle); + else + handles[size] = HandleList(1, handle); + + handle->AddReference(); + + return handle; } // Releases the face's FreeType face structure. void FontFace::ReleaseFace() { - if (face != NULL) - { - FT_Byte* face_memory = face->stream->base; - FT_Done_Face(face); + if (face != NULL) + { + FT_Byte* face_memory = face->stream->base; + FT_Done_Face(face); - if (release_stream) - delete[] face_memory; + if (release_stream) + delete[] face_memory; - face = NULL; - } + face = NULL; + } } } diff --git a/Source/Core/FreeType/FontFace.h b/Source/Core/FreeType/FontFace.h index 941090604..c361d7768 100644 --- a/Source/Core/FreeType/FontFace.h +++ b/Source/Core/FreeType/FontFace.h @@ -36,7 +36,7 @@ namespace Rocket { namespace Core { namespace FreeType { /** - @author Peter Curry + @author Peter Curry */ class FontFaceHandle; @@ -44,21 +44,21 @@ class FontFaceHandle; class FontFace : public Rocket::Core::FontFace { public: - FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream); - ~FontFace(); + FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream); + ~FontFace(); - /// Returns a handle for positioning and rendering this face at the given size. - /// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges. - /// @param[in] size The size of the desired handle, in points. - /// @return The shared font handle. - Rocket::Core::FontFaceHandle* GetHandle(const String& charset, int size); + /// 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(); + /// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed, + /// but existing ones can still be fetched. + void ReleaseFace(); private: - FT_Face face; + FT_Face face; }; } diff --git a/Source/Core/FreeType/FontFaceHandle.cpp b/Source/Core/FreeType/FontFaceHandle.cpp index f201d0bba..350934341 100644 --- a/Source/Core/FreeType/FontFaceHandle.cpp +++ b/Source/Core/FreeType/FontFaceHandle.cpp @@ -39,15 +39,15 @@ namespace FreeType { class FontEffectSort { public: - bool operator()(const FontEffect* lhs, const FontEffect* rhs) - { - return lhs->GetZIndex() < rhs->GetZIndex(); - } + bool operator()(const FontEffect* lhs, const FontEffect* rhs) + { + return lhs->GetZIndex() < rhs->GetZIndex(); + } }; FontFaceHandle::FontFaceHandle() { - ft_face = NULL; + ft_face = NULL; } FontFaceHandle::~FontFaceHandle() @@ -57,400 +57,400 @@ 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; + 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; - } + 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; - } + // 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; + 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); + // 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]); + // 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 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); + // 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; + 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; + int width = 0; - for (size_t i = 0; i < string.Length(); i++) - { - word character_code = string[i]; + 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]; + 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; + // 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; - } + prior_character = character_code; + } - return width; + 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); + 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; + 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); + 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; + int geometry_index = 0; + int line_width = 0; - ROCKET_ASSERT(layer_configuration_index >= 0); - ROCKET_ASSERT(layer_configuration_index < (int) layer_configurations.size()); + 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]; + // 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(); + 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()); + // 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)); + // 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; + line_width = 0; + word prior_character = 0; - const word* string_iterator = string.CString(); - const word* string_end = string.CString() + string.Length(); + 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]; + 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); + // 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); + layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour); - line_width += glyph.advance; - prior_character = *string_iterator; - } + line_width += glyph.advance; + prior_character = *string_iterator; + } - geometry_index += layer->GetNumTextures(); - } + geometry_index += layer->GetNumTextures(); + } - // Cull any excess geometry from a previous generation. - geometry.resize(geometry_index); + // Cull any excess geometry from a previous generation. + geometry.resize(geometry_index); - return line_width; + 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); + 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; + 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; + 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; - } - } + 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; + // 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 (!FT_HAS_KERNING(ft_face)) + return 0; - FT_Vector ft_kerning; + 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); + 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; + if (ft_error != 0) + return 0; - int kerning = ft_kerning.x >> 6; - return kerning; + int kerning = ft_kerning.x >> 6; + return kerning; } } diff --git a/Source/Core/FreeType/FontFaceHandle.h b/Source/Core/FreeType/FontFaceHandle.h index 84810bc4f..2654ee5bf 100644 --- a/Source/Core/FreeType/FontFaceHandle.h +++ b/Source/Core/FreeType/FontFaceHandle.h @@ -47,67 +47,67 @@ class FontFaceLayer; namespace FreeType { /** - @author Peter Curry + @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; + 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(); + /// Destroys the handle. + virtual void OnReferenceDeactivate(); - int GetKerning(word lhs, word rhs) const; + int GetKerning(word lhs, word rhs) const; private: - void GenerateMetrics(void); + void GenerateMetrics(void); - void BuildGlyphMap(const UnicodeRange& unicode_range); - void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph); + void BuildGlyphMap(const UnicodeRange& unicode_range); + void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph); - FT_Face ft_face; + FT_Face ft_face; }; } diff --git a/Source/Core/FreeType/FontFamily.cpp b/Source/Core/FreeType/FontFamily.cpp index c389c89b9..431d1a6d3 100644 --- a/Source/Core/FreeType/FontFamily.cpp +++ b/Source/Core/FreeType/FontFamily.cpp @@ -47,10 +47,10 @@ FontFamily::~FontFamily() // Adds a new face to the family. bool FontFamily::AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream) { - FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream); - font_faces.push_back(face); + FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream); + font_faces.push_back(face); - return true; + return true; } } diff --git a/Source/Core/FreeType/FontFamily.h b/Source/Core/FreeType/FontFamily.h index f95be801a..4d5b75ffc 100644 --- a/Source/Core/FreeType/FontFamily.h +++ b/Source/Core/FreeType/FontFamily.h @@ -40,7 +40,7 @@ class FontFace; class FontFaceHandle; /** - @author Peter Curry + @author Peter Curry */ namespace FreeType { @@ -48,16 +48,16 @@ namespace FreeType { class FontFamily : public Rocket::Core::FontFamily { public: - FontFamily(const String& name); - ~FontFamily(); + FontFamily(const String& name); + ~FontFamily(); - /// Adds a new face to the family. - /// @param[in] ft_face The previously loaded FreeType face. - /// @param[in] style The style of the new face. - /// @param[in] weight The weight of the new face. - /// @param[in] release_stream True if the application must free the face's memory stream. - /// @return True if the face was loaded successfully, false otherwise. - bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream); + /// Adds a new face to the family. + /// @param[in] ft_face The previously loaded FreeType face. + /// @param[in] style The style of the new face. + /// @param[in] weight The weight of the new face. + /// @param[in] release_stream True if the application must free the face's memory stream. + /// @return True if the face was loaded successfully, false otherwise. + bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream); }; } diff --git a/Source/Core/FreeType/FontProvider.cpp b/Source/Core/FreeType/FontProvider.cpp index b0ca2db4a..c2f098829 100644 --- a/Source/Core/FreeType/FontProvider.cpp +++ b/Source/Core/FreeType/FontProvider.cpp @@ -44,213 +44,213 @@ static FT_Library ft_library = NULL; FontProvider::FontProvider() { - ROCKET_ASSERT(instance == NULL); - instance = this; + ROCKET_ASSERT(instance == NULL); + instance = this; } FontProvider::~FontProvider() { - ROCKET_ASSERT(instance == this); - instance = NULL; + ROCKET_ASSERT(instance == this); + instance = NULL; } bool FontProvider::Initialise() { - if (instance == NULL) - { - new FontProvider(); - - FontDatabase::AddFontProvider(instance); - - FT_Error result = FT_Init_FreeType(&ft_library); - if (result != 0) - { - Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result); - Shutdown(); - return false; - } - } - - return true; + if (instance == NULL) + { + new FontProvider(); + + FontDatabase::AddFontProvider(instance); + + FT_Error result = FT_Init_FreeType(&ft_library); + if (result != 0) + { + Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result); + Shutdown(); + return false; + } + } + + return true; } void FontProvider::Shutdown() { - if (instance != NULL) - { - for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i) - delete (*i).second; - - if (ft_library != NULL) - { - FT_Done_FreeType(ft_library); - ft_library = NULL; - } - - delete instance; - } + if (instance != NULL) + { + for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i) + delete (*i).second; + + if (ft_library != NULL) + { + FT_Done_FreeType(ft_library); + ft_library = NULL; + } + + delete instance; + } } // Loads a new font face. bool FontProvider::LoadFontFace(const String& file_name) { - FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); - return false; - } - - Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; - - if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return false; - } + FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); + return false; + } + + Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; + Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; + + if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return false; + } } // Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself. bool FontProvider::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight) { - FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); - return false; - } - - if (instance->AddFace(ft_face, family, style, weight, true)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); - return false; - } + FT_Face ft_face = (FT_Face) instance->LoadFace(file_name); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString()); + return false; + } + + if (instance->AddFace(ft_face, family, style, weight, true)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString()); + return false; + } } // Adds a new font face to the database, loading from memory. bool FontProvider::LoadFontFace(const byte* data, int data_length) { - FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); - return false; - } - - Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; - Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; - - if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return false; - } + FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); + return false; + } + + Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL; + Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL; + + if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return false; + } } // Adds a new font face to the database, loading from memory, ignoring any family, style and weight information stored in the face itself. bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight) { - FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); - if (ft_face == NULL) - { - Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); - return false; - } - - if (instance->AddFace(ft_face, family, style, weight, false)) - { - Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return true; - } - else - { - Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); - return false; - } + FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false); + if (ft_face == NULL) + { + Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream."); + return false; + } + + if (instance->AddFace(ft_face, family, style, weight, false)) + { + Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return true; + } + else + { + Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name); + return false; + } } // Adds a loaded face to the appropriate font family. bool FontProvider::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream) { - FontFamily* font_family = NULL; - FontFamilyMap::iterator iterator = font_families.find(family); - if (iterator != font_families.end()) - font_family = (FontFamily*)(*iterator).second; - else - { - font_family = new FontFamily(family); - font_families[family] = font_family; - } - - return font_family->AddFace((FT_Face) face, style, weight, release_stream); + FontFamily* font_family = NULL; + FontFamilyMap::iterator iterator = font_families.find(family); + if (iterator != font_families.end()) + font_family = (FontFamily*)(*iterator).second; + else + { + font_family = new FontFamily(family); + font_families[family] = font_family; + } + + return font_family->AddFace((FT_Face) face, style, weight, release_stream); } // Loads a FreeType face. void* FontProvider::LoadFace(const String& file_name) { - FileInterface* file_interface = GetFileInterface(); - FileHandle handle = file_interface->Open(file_name); + FileInterface* file_interface = GetFileInterface(); + FileHandle handle = file_interface->Open(file_name); - if (!handle) - { - return NULL; - } + if (!handle) + { + return NULL; + } - size_t length = file_interface->Length(handle); + size_t length = file_interface->Length(handle); - FT_Byte* buffer = new FT_Byte[length]; - file_interface->Read(buffer, length, handle); - file_interface->Close(handle); + FT_Byte* buffer = new FT_Byte[length]; + file_interface->Read(buffer, length, handle); + file_interface->Close(handle); - return LoadFace(buffer, (int)length, file_name, true); + return LoadFace(buffer, (int)length, file_name, true); } // Loads a FreeType face from memory. void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data) { - FT_Face face = NULL; - int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face); - if (error != 0) - { - Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString()); - if (local_data) - delete[] data; - - return NULL; - } - - // Initialise the character mapping on the face. - if (face->charmap == NULL) - { - FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); - if (face->charmap == NULL) - { - Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString()); - FT_Done_Face(face); - if (local_data) - delete[] data; - - return NULL; - } - } - - return face; + FT_Face face = NULL; + int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face); + if (error != 0) + { + Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString()); + if (local_data) + delete[] data; + + return NULL; + } + + // Initialise the character mapping on the face. + if (face->charmap == NULL) + { + FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); + if (face->charmap == NULL) + { + Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString()); + FT_Done_Face(face); + if (local_data) + delete[] data; + + return NULL; + } + } + + return face; } } From a3b7be8332e4059b45ca6a8a8a6d3aa8189bad5f Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Thu, 3 Sep 2015 18:57:29 +0200 Subject: [PATCH 12/13] tabs instead of spaces 2 --- Source/Core/TextureLayoutTexture.cpp | 6 +++--- Source/Debugger/Plugin.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/TextureLayoutTexture.cpp b/Source/Core/TextureLayoutTexture.cpp index 607ce25f1..e0ef51bd1 100644 --- a/Source/Core/TextureLayoutTexture.cpp +++ b/Source/Core/TextureLayoutTexture.cpp @@ -65,10 +65,10 @@ int TextureLayoutTexture::Generate(TextureLayout& layout, int maximum_dimensions if (!rectangle.IsPlaced()) { - int x = rectangle.GetDimensions().x + 1; - int y = rectangle.GetDimensions().y + 1; + int x = rectangle.GetDimensions().x + 1; + int y = rectangle.GetDimensions().y + 1; - square_pixels += x*y; + square_pixels += x*y; ++unplaced_rectangles; } } diff --git a/Source/Debugger/Plugin.cpp b/Source/Debugger/Plugin.cpp index 6184d4c5a..867f0cd50 100644 --- a/Source/Debugger/Plugin.cpp +++ b/Source/Debugger/Plugin.cpp @@ -286,8 +286,8 @@ Plugin* Plugin::GetInstance() bool Plugin::LoadFont() { - return (Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_regular, sizeof(lacuna_regular) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_NORMAL, Core::Font::WEIGHT_NORMAL) && - Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_italic, sizeof(lacuna_italic) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_ITALIC, Core::Font::WEIGHT_NORMAL)); + return (Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_regular, sizeof(lacuna_regular) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_NORMAL, Core::Font::WEIGHT_NORMAL) && + Core::FontDatabase::LoadFontFace(Core::FontDatabase::FreeType, lacuna_italic, sizeof(lacuna_italic) / sizeof(unsigned char), "Lacuna", Core::Font::STYLE_ITALIC, Core::Font::WEIGHT_NORMAL)); } bool Plugin::LoadMenuElement() From caf6eefbbacbbf3683114ed1655664582e0f1a29 Mon Sep 17 00:00:00 2001 From: Patryk Konopka Date: Thu, 3 Sep 2015 19:00:35 +0200 Subject: [PATCH 13/13] Build samples OFF --- Build/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build/CMakeLists.txt b/Build/CMakeLists.txt index 1fce0fb5f..23ce499fd 100644 --- a/Build/CMakeLists.txt +++ b/Build/CMakeLists.txt @@ -141,7 +141,7 @@ if(APPLE) option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF) endif() -option(BUILD_SAMPLES "Build samples" ON) +option(BUILD_SAMPLES "Build samples" OFF) if(WIN32) option(SKIP_DIRECTX_SAMPLES "Skip build of all DirectX related samples. Only applies if BUILD_SAMPLES is ON" OFF) option(SKIP_DIRECTX9_SAMPLE "Skip build of DirectX 9 related sample. Only applies if BUILD_SAMPLES is ON and SKIP_DIRECTX_SAMPLES is OFF" OFF)