diff --git a/data/stk_config.xml b/data/stk_config.xml index c3924751c..8b2259340 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -411,8 +411,7 @@ which leads to crash with STK), but the fonts are to blame, what's the point of not using industry standard nowadays... --> - + diff --git a/data/ttf/Cantarell-Bold.otf b/data/ttf/Cantarell-Bold.otf deleted file mode 100644 index 0d0f3afbd..000000000 Binary files a/data/ttf/Cantarell-Bold.otf and /dev/null differ diff --git a/data/ttf/FreeSansBold.ttf b/data/ttf/FreeSansBold.ttf deleted file mode 100644 index 6f36dc5fe..000000000 Binary files a/data/ttf/FreeSansBold.ttf and /dev/null differ diff --git a/data/ttf/LICENSE b/data/ttf/LICENSE index a65321afc..e595c3831 100644 --- a/data/ttf/LICENSE +++ b/data/ttf/LICENSE @@ -1,4 +1,4 @@ -GNU FreeFont (FreeSans, FreeSansBold) is released under the GPLv3 +GNU FreeFont (FreeSans) is released under the GPLv3 wqyMicroHei is released under the GPLv3 with font embedding exception and Apache-2.0 licenses By Qianqian Fang and The WenQuanYi Project Contributors diff --git a/sources.cmake b/sources.cmake index ddc029d4f..f484b15d5 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,5 +1,5 @@ # Modify this file to change the last-modified date when you add/remove a file. -# This will then trigger a new cmake run automatically. +# This will then trigger a new cmake run automatically. file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp") file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp") file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*") diff --git a/src/config/stk_config.cpp b/src/config/stk_config.cpp index d6701c680..288fef4c8 100644 --- a/src/config/stk_config.cpp +++ b/src/config/stk_config.cpp @@ -182,9 +182,8 @@ void STKConfig::init_defaults() m_score_increase.clear(); m_leader_intervals.clear(); m_switch_items.clear(); - m_regular_faces.clear(); - m_bold_faces.clear(); - m_digit_faces.clear(); + m_normal_ttf.clear(); + m_digit_ttf.clear(); } // init_defaults //----------------------------------------------------------------------------- @@ -368,9 +367,8 @@ void STKConfig::getAllData(const XMLNode * root) if (const XMLNode *fonts_list = root->getNode("fonts-list")) { - fonts_list->get("regular-faces", &m_regular_faces); - fonts_list->get("bold-faces", &m_bold_faces ); - fonts_list->get("digit-faces", &m_digit_faces ); + fonts_list->get("normal-ttf", &m_normal_ttf); + fonts_list->get("digit-ttf", &m_digit_ttf ); } // Get the default KartProperties diff --git a/src/config/stk_config.hpp b/src/config/stk_config.hpp index 898d02ef8..21a8c678a 100644 --- a/src/config/stk_config.hpp +++ b/src/config/stk_config.hpp @@ -154,9 +154,8 @@ public: std::string m_font_bold_fallback; std::string m_font_digit; /** Lists of TTF files used in STK. */ - std::vector m_regular_faces; - std::vector m_bold_faces; - std::vector m_digit_faces; + std::vector m_normal_ttf; + std::vector m_digit_ttf; private: /** True if stk_config has been loaded. This is necessary if the diff --git a/src/font/bold_face.cpp b/src/font/bold_face.cpp index 3efa6dc14..f32aea7b5 100644 --- a/src/font/bold_face.cpp +++ b/src/font/bold_face.cpp @@ -18,11 +18,10 @@ #include "font/bold_face.hpp" -#include "config/stk_config.hpp" -#include "font/regular_face.hpp" +#include "font/face_ttf.hpp" // ---------------------------------------------------------------------------- -BoldFace::BoldFace() : FontWithFace("BoldFace") +BoldFace::BoldFace(FaceTTF* ttf) : FontWithFace("BoldFace", ttf) { } // BoldFace @@ -32,8 +31,10 @@ void BoldFace::init() FontWithFace::init(); // Reserve some space for characters added later m_font_max_height = m_glyph_max_height + 20; + + /* Use FT_Outline_Embolden for now, no more fallback font setFallbackFont(font_manager->getFont()); - setFallbackFontScale(2.0f); + setFallbackFontScale(2.0f);*/ } // init // ---------------------------------------------------------------------------- @@ -51,9 +52,3 @@ void BoldFace::reset() insertCharacters(preload_chars.c_str()); updateCharactersList(); } // reset - -// ---------------------------------------------------------------------------- -std::vector BoldFace::getFacesList() const -{ - return stk_config->m_bold_faces; -} // getFacesList diff --git a/src/font/bold_face.hpp b/src/font/bold_face.hpp index f4f91a10e..53ddce8f5 100644 --- a/src/font/bold_face.hpp +++ b/src/font/bold_face.hpp @@ -21,11 +21,11 @@ #include "font/font_with_face.hpp" +class FaceTTF; + class BoldFace : public FontWithFace { private: - virtual std::vector getFacesList() const OVERRIDE; - // ------------------------------------------------------------------------ virtual bool supportLazyLoadChar() const OVERRIDE { return true; } // ------------------------------------------------------------------------ virtual unsigned int getGlyphPageSize() const OVERRIDE { return 1024; } @@ -37,7 +37,7 @@ private: public: LEAK_CHECK() // ------------------------------------------------------------------------ - BoldFace(); + BoldFace(FaceTTF* ttf); // ------------------------------------------------------------------------ virtual ~BoldFace() {} // ------------------------------------------------------------------------ diff --git a/src/font/digit_face.cpp b/src/font/digit_face.cpp index 672211b94..7b257fce5 100644 --- a/src/font/digit_face.cpp +++ b/src/font/digit_face.cpp @@ -18,10 +18,10 @@ #include "font/digit_face.hpp" -#include "config/stk_config.hpp" +#include "font/face_ttf.hpp" // ---------------------------------------------------------------------------- -DigitFace::DigitFace() : FontWithFace("DigitFace") +DigitFace::DigitFace(FaceTTF* ttf) : FontWithFace("DigitFace", ttf) { } // DigitFace @@ -50,9 +50,3 @@ void DigitFace::reset() insertCharacters(preload_chars.c_str(), true/*first_load*/); updateCharactersList(); } // reset - -// ---------------------------------------------------------------------------- -std::vector DigitFace::getFacesList() const -{ - return stk_config->m_digit_faces; -} // getFacesList diff --git a/src/font/digit_face.hpp b/src/font/digit_face.hpp index 4ff08be62..35bbdb248 100644 --- a/src/font/digit_face.hpp +++ b/src/font/digit_face.hpp @@ -21,11 +21,11 @@ #include "font/font_with_face.hpp" +class FaceTTF; + class DigitFace : public FontWithFace { private: - virtual std::vector getFacesList() const OVERRIDE; - // ------------------------------------------------------------------------ virtual bool supportLazyLoadChar() const OVERRIDE { return false; } // ------------------------------------------------------------------------ virtual unsigned int getGlyphPageSize() const OVERRIDE { return 256; } @@ -37,7 +37,7 @@ private: public: LEAK_CHECK() // ------------------------------------------------------------------------ - DigitFace(); + DigitFace(FaceTTF* ttf); // ------------------------------------------------------------------------ virtual ~DigitFace() {} // ------------------------------------------------------------------------ diff --git a/src/font/face_ttf.cpp b/src/font/face_ttf.cpp new file mode 100644 index 000000000..fdb64d572 --- /dev/null +++ b/src/font/face_ttf.cpp @@ -0,0 +1,49 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2016 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "font/face_ttf.hpp" + +#include "io/file_manager.hpp" + +// ---------------------------------------------------------------------------- +FaceTTF::FaceTTF(const std::vector& ttf_list) +{ + for (const std::string& font : ttf_list) + { + FT_Face face = NULL; + font_manager->checkFTError(FT_New_Face(font_manager->getFTLibrary(), + (file_manager->getAssetChecked(FileManager::TTF, + font.c_str(), true)).c_str(), 0, &face), "loading fonts"); + m_faces.push_back(face); + } +} // FaceTTF + +// ---------------------------------------------------------------------------- +FaceTTF::~FaceTTF() +{ + for (unsigned int i = 0; i < m_faces.size(); i++) + { + font_manager->checkFTError(FT_Done_Face(m_faces[i]), "removing face"); + } +} // ~FaceTTF +// ---------------------------------------------------------------------------- +FT_Face FaceTTF::getFace(unsigned int i) const +{ + assert(i < m_faces.size()); + return m_faces[i]; +} // getFace diff --git a/src/font/face_ttf.hpp b/src/font/face_ttf.hpp new file mode 100644 index 000000000..90663dab5 --- /dev/null +++ b/src/font/face_ttf.hpp @@ -0,0 +1,43 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2016 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_FACE_TTF_HPP +#define HEADER_FACE_TTF_HPP + +#include "font/font_manager.hpp" + +class FaceTTF : public NoCopy +{ +private: + std::vector m_faces; + +public: + LEAK_CHECK(); + // ------------------------------------------------------------------------ + FaceTTF(const std::vector& ttf_list); + // ------------------------------------------------------------------------ + ~FaceTTF(); + // ------------------------------------------------------------------------ + FT_Face getFace(unsigned int i) const; + // ------------------------------------------------------------------------ + unsigned int getTotalFaces() const { return m_faces.size(); } + +}; // FaceTTF + +#endif +/* EOF */ diff --git a/src/font/font_manager.cpp b/src/font/font_manager.cpp index 2d839b997..772c7de22 100644 --- a/src/font/font_manager.cpp +++ b/src/font/font_manager.cpp @@ -18,8 +18,10 @@ #include "font/font_manager.hpp" +#include "config/stk_config.hpp" #include "font/bold_face.hpp" #include "font/digit_face.hpp" +#include "font/face_ttf.hpp" #include "font/regular_face.hpp" FontManager *font_manager = NULL; @@ -33,6 +35,11 @@ FontManager::FontManager() FontManager::~FontManager() { m_fonts.clearAndDeleteAll(); + delete m_normal_ttf; + m_normal_ttf = NULL; + delete m_digit_ttf; + m_digit_ttf = NULL; + checkFTError(FT_Done_FreeType(m_ft_library), "removing freetype library"); m_ft_library = NULL; } // ~FontManager @@ -40,13 +47,20 @@ FontManager::~FontManager() // ---------------------------------------------------------------------------- void FontManager::loadFonts() { - RegularFace* regular = new RegularFace(); + // First load the TTF files required by each font + m_normal_ttf = new FaceTTF(stk_config->m_normal_ttf); + m_digit_ttf = new FaceTTF(stk_config->m_digit_ttf); + + // Now load fonts with settings of ttf file + RegularFace* regular = new RegularFace(m_normal_ttf); regular->init(); m_fonts.push_back(regular); - BoldFace* bold = new BoldFace(); + + BoldFace* bold = new BoldFace(m_normal_ttf); bold->init(); m_fonts.push_back(bold); - DigitFace* digit = new DigitFace(); + + DigitFace* digit = new DigitFace(m_digit_ttf); digit->init(); m_fonts.push_back(digit); } // loadFonts diff --git a/src/font/font_manager.hpp b/src/font/font_manager.hpp index 6ceec0799..68f2118cc 100644 --- a/src/font/font_manager.hpp +++ b/src/font/font_manager.hpp @@ -29,6 +29,7 @@ #include #include FT_FREETYPE_H +class FaceTTF; class FontWithFace; class FontManager : public NoCopy @@ -38,6 +39,10 @@ private: FT_Library m_ft_library; + FaceTTF* m_normal_ttf; + + FaceTTF* m_digit_ttf; + public: LEAK_CHECK() // ------------------------------------------------------------------------ diff --git a/src/font/font_with_face.cpp b/src/font/font_with_face.cpp index e432a161e..579169131 100644 --- a/src/font/font_with_face.cpp +++ b/src/font/font_with_face.cpp @@ -19,14 +19,17 @@ #include "font/font_with_face.hpp" #include "font/bold_face.hpp" +#include "font/face_ttf.hpp" #include "graphics/2dutils.hpp" #include "graphics/irr_driver.hpp" #include "guiengine/engine.hpp" #include "guiengine/skin.hpp" #include "utils/string_utils.hpp" +#include + // ---------------------------------------------------------------------------- -FontWithFace::FontWithFace(const std::string& name) +FontWithFace::FontWithFace(const std::string& name, FaceTTF* ttf) { m_spritebank = irr_driver->getGUI()->addEmptySpriteBank(name.c_str()); @@ -36,6 +39,7 @@ FontWithFace::FontWithFace(const std::string& name) m_fallback_font = NULL; m_fallback_font_scale = 1.0f; m_glyph_max_height = 0; + m_face_ttf = ttf; } // FontWithFace // ---------------------------------------------------------------------------- @@ -46,33 +50,24 @@ FontWithFace::~FontWithFace() m_spritebank->drop(); m_spritebank = NULL; - for (unsigned int i = 0; i < m_faces.size(); i++) - { - font_manager->checkFTError(FT_Done_Face(m_faces[i]), "removing face"); - } + // To be deleted by font_manager + m_face_ttf = NULL; } // ~FontWithFace // ---------------------------------------------------------------------------- void FontWithFace::init() { + setDPI(); m_page = irr_driver->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(getGlyphPageSize(), getGlyphPageSize())); - for (const std::string& font : getFacesList()) - { - FT_Face face = NULL; - font_manager->checkFTError(FT_New_Face(font_manager->getFTLibrary(), - (file_manager->getAssetChecked(FileManager::TTF, - font.c_str(), true)).c_str(), 0, &face), "loading fonts"); - font_manager->checkFTError(FT_Set_Pixel_Sizes(face, 0, getDPI()), - "setting DPI"); - m_faces.push_back(face); - } - // Get the max height for this face - assert(m_faces.size() > 0); - FT_Face cur_face = m_faces[0]; + assert(m_face_ttf->getTotalFaces() > 0); + FT_Face cur_face = m_face_ttf->getFace(0); + font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()), + "setting DPI"); + for (int i = 32; i < 128; i++) { // Test all basic latin characters @@ -98,6 +93,20 @@ void FontWithFace::reset() createNewGlyphPage(); } // reset +// ---------------------------------------------------------------------------- +void FontWithFace::loadGlyphInfo(wchar_t c) +{ + unsigned int font_number = 0; + unsigned int glyph_index = 0; + while (font_number < m_face_ttf->getTotalFaces()) + { + glyph_index = FT_Get_Char_Index(m_face_ttf->getFace(font_number), c); + if (glyph_index > 0) break; + font_number++; + } + m_character_glyph_info_map[c] = GlyphInfo(font_number, glyph_index); +} // loadGlyphInfo + // ---------------------------------------------------------------------------- void FontWithFace::createNewGlyphPage() { @@ -124,13 +133,26 @@ void FontWithFace::createNewGlyphPage() void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi) { assert(gi.glyph_index > 0); - assert(gi.font_number < m_faces.size()); - FT_Face cur_face = m_faces[gi.font_number]; + assert(gi.font_number < m_face_ttf->getTotalFaces()); + FT_Face cur_face = m_face_ttf->getFace(gi.font_number); FT_GlyphSlot slot = cur_face->glyph; + // Faces may be shared across regular and bold, + // so reset dpi each time + font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()), + "setting DPI"); + font_manager->checkFTError(FT_Load_Glyph(cur_face, gi.glyph_index, - FT_LOAD_DEFAULT | FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL), - "loading a glyph"); + FT_LOAD_DEFAULT), "loading a glyph"); + + if (dynamic_cast(this)) + { + // Embolden the outline of the glyph + FT_Outline_Embolden(&(slot->outline), getDPI() * 2); + } + + font_manager->checkFTError(FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL), + "render a glyph to bitmap"); // Convert to an anti-aliased bitmap FT_Bitmap bits = slot->bitmap; @@ -297,7 +319,7 @@ void FontWithFace::dumpGlyphPage() } // dumpGlyphPage // ---------------------------------------------------------------------------- -unsigned int FontWithFace::getDPI() const +void FontWithFace::setDPI() { // Get face dpi: // Font size is resolution-dependent. @@ -315,10 +337,10 @@ unsigned int FontWithFace::getDPI() const if (screen_width < 900 || screen_height < 700) scale = std::min(scale, 0.05f); - return unsigned((getScalingFactorOne() + 0.2f * scale) * + m_face_dpi = unsigned((getScalingFactorOne() + 0.2f * scale) * getScalingFactorTwo()); -} // getDPI +} // setDPI // ---------------------------------------------------------------------------- const FontWithFace::FontArea& diff --git a/src/font/font_with_face.hpp b/src/font/font_with_face.hpp index 239066fb4..e219c9c30 100644 --- a/src/font/font_with_face.hpp +++ b/src/font/font_with_face.hpp @@ -29,6 +29,8 @@ const int BEARING = 64; +class FaceTTF; + class FontWithFace : public NoCopy { public: @@ -53,8 +55,6 @@ public: }; protected: - std::vector m_faces; - int m_font_max_height; int m_glyph_max_height; @@ -104,6 +104,8 @@ private: } }; + FaceTTF* m_face_ttf; + FontWithFace* m_fallback_font; float m_fallback_font_scale; @@ -120,6 +122,7 @@ private: unsigned int m_temp_height; unsigned int m_used_width; unsigned int m_used_height; + unsigned int m_face_dpi; std::map m_character_area_map; std::map m_character_glyph_info_map; @@ -162,27 +165,16 @@ private: return false; } // ------------------------------------------------------------------------ - void loadGlyphInfo(wchar_t c) - { - unsigned int font_number = 0; - unsigned int glyph_index = 0; - while (font_number < m_faces.size()) - { - glyph_index = FT_Get_Char_Index(m_faces[font_number], c); - if (glyph_index > 0) break; - font_number++; - } - m_character_glyph_info_map[c] = GlyphInfo(font_number, glyph_index); - } + void loadGlyphInfo(wchar_t c); // ------------------------------------------------------------------------ void createNewGlyphPage(); // ------------------------------------------------------------------------ - unsigned int getDPI() const; - // ------------------------------------------------------------------------ void addLazyLoadChar(wchar_t c) { m_new_char_holder.insert(c); } // ------------------------------------------------------------------------ void insertGlyph(wchar_t c, const GlyphInfo& gi); // ------------------------------------------------------------------------ + void setDPI(); + // ------------------------------------------------------------------------ virtual bool supportLazyLoadChar() const = 0; // ------------------------------------------------------------------------ virtual unsigned int getGlyphPageSize() const = 0; @@ -190,13 +182,11 @@ private: virtual float getScalingFactorOne() const = 0; // ------------------------------------------------------------------------ virtual unsigned int getScalingFactorTwo() const = 0; - // ------------------------------------------------------------------------ - virtual std::vector getFacesList() const = 0; public: LEAK_CHECK(); // ------------------------------------------------------------------------ - FontWithFace(const std::string& name); + FontWithFace(const std::string& name, FaceTTF* ttf); // ------------------------------------------------------------------------ virtual ~FontWithFace(); // ------------------------------------------------------------------------ @@ -231,6 +221,8 @@ public: // ------------------------------------------------------------------------ const FontArea& getAreaFromCharacter(const wchar_t c, bool* fallback_font) const; + // ------------------------------------------------------------------------ + unsigned int getDPI() const { return m_face_dpi; } }; // FontWithFace diff --git a/src/font/regular_face.cpp b/src/font/regular_face.cpp index c764d894b..f86a9ffc1 100644 --- a/src/font/regular_face.cpp +++ b/src/font/regular_face.cpp @@ -16,12 +16,12 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#include "font/face_ttf.hpp" + #include "font/regular_face.hpp" -#include "config/stk_config.hpp" - // ---------------------------------------------------------------------------- -RegularFace::RegularFace() : FontWithFace("RegularFace") +RegularFace::RegularFace(FaceTTF* ttf) : FontWithFace("RegularFace", ttf) { } // RegularFace @@ -48,9 +48,3 @@ void RegularFace::reset() insertCharacters(preload_chars.c_str()); updateCharactersList(); } // reset - -// ---------------------------------------------------------------------------- -std::vector RegularFace::getFacesList() const -{ - return stk_config->m_regular_faces; -} // getFacesList diff --git a/src/font/regular_face.hpp b/src/font/regular_face.hpp index 4ddecf24c..54ac41d4a 100644 --- a/src/font/regular_face.hpp +++ b/src/font/regular_face.hpp @@ -21,11 +21,11 @@ #include "font/font_with_face.hpp" +class FaceTTF; + class RegularFace : public FontWithFace { private: - virtual std::vector getFacesList() const OVERRIDE; - // ------------------------------------------------------------------------ virtual bool supportLazyLoadChar() const OVERRIDE { return true; } // ------------------------------------------------------------------------ virtual unsigned int getGlyphPageSize() const OVERRIDE { return 512; } @@ -37,7 +37,7 @@ private: public: LEAK_CHECK() // ------------------------------------------------------------------------ - RegularFace(); + RegularFace(FaceTTF* ttf); // ------------------------------------------------------------------------ virtual ~RegularFace() {} // ------------------------------------------------------------------------