1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2016 SuperTuxKart-Team
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #ifndef HEADER_FONT_MANAGER_HPP
20 #define HEADER_FONT_MANAGER_HPP
21 
22 /** \defgroup font Font
23  *  This module stores font files and tools used to draw characters in STK.
24  */
25 
26 #include "utils/leak_check.hpp"
27 #include "utils/log.hpp"
28 #include "utils/no_copy.hpp"
29 
30 #include <string>
31 #include <map>
32 #include <typeindex>
33 #include <unordered_map>
34 #include <vector>
35 
36 #ifndef SERVER_ONLY
37 #include <ft2build.h>
38 #include <harfbuzz/hb.h>
39 #include FT_FREETYPE_H
40 
41 #include "irrString.h"
42 #include "GlyphLayout.h"
43 #endif
44 
45 class FontWithFace;
46 
47 /** This class stores all font files required in STK.
48  *  \ingroup font
49  */
50 class FontManager : public NoCopy
51 {
52 private:
53     /** Stores all \ref FontWithFace used in STK. */
54     std::vector<FontWithFace*>               m_fonts;
55 
56 #ifndef SERVER_ONLY
57     /** A FreeType library, it holds the FT_Face internally inside freetype. */
58     FT_Library                               m_ft_library;
59 
60     /** List of TTF files for complex text shaping. */
61     std::vector<FT_Face>                     m_faces;
62 
63     /** TTF file for digit font in STK. */
64     FT_Face                                  m_digit_face;
65 
66     /** DPI used when shaping, each face will apply an inverse of this and the
67      *  dpi of itself when rendering, so all faces can share the same glyph
68      *  layout cache. */
69     unsigned m_shaping_dpi;
70 
71     /** Map FT_Face to index for quicker layout. */
72     std::map<FT_Face, uint16_t> m_ft_faces_to_index;
73 
74     /** Text drawn to glyph layouts cache. */
75     std::map<irr::core::stringw,
76         std::vector<irr::gui::GlyphLayout> > m_cached_gls;
77 
78     bool m_has_color_emoji;
79     // ------------------------------------------------------------------------
80     std::vector<FT_Face> loadTTF(const std::vector<std::string>& ttf_list);
81 
82     hb_buffer_t* m_hb_buffer;
83 
84     std::vector<hb_font_t*> m_hb_fonts;
85 #endif
86 
87     /** Map type for each \ref FontWithFace with a index, save getting time in
88      *  \ref getFont. */
89     std::unordered_map<std::type_index, int> m_font_type_map;
90 public:
91     LEAK_CHECK()
92     // ------------------------------------------------------------------------
93     FontManager();
94     // ------------------------------------------------------------------------
95     ~FontManager();
96     // ------------------------------------------------------------------------
97     /** Return a specfic type of \ref FontWithFace found in \ref m_fonts. */
getFont()98     template <typename T> T* getFont()
99     {
100         T* out = NULL;
101         const unsigned int n = m_font_type_map[std::type_index(typeid(T))];
102         out = dynamic_cast<T*>(m_fonts[n]);
103         if (out != NULL)
104         {
105             return out;
106         }
107         Log::fatal("FontManager", "Can't get a font!");
108         return out;
109     }
110     // ------------------------------------------------------------------------
111 #ifndef SERVER_ONLY
112     /** Check for any error discovered in a freetype function that will return
113      *  a FT_Error value, and log into the terminal.
114      *  \param err The Freetype function.
115      *  \param desc The description of what is the function doing. */
checkFTError(FT_Error err,const std::string & desc) const116     void checkFTError(FT_Error err, const std::string& desc) const
117     {
118         if (err > 0)
119         {
120             Log::error("FontManager", "Something wrong when %s! The error "
121                 "code was %d.", desc.c_str(), err);
122         }
123     }
124     // ------------------------------------------------------------------------
hasColorEmoji() const125     bool hasColorEmoji() const                    { return m_has_color_emoji; }
126     // ------------------------------------------------------------------------
127     /** Return the \ref m_ft_library. */
getFTLibrary() const128     FT_Library getFTLibrary() const                    { return m_ft_library; }
129     // ------------------------------------------------------------------------
130     FT_Face loadColorEmoji();
131     // ------------------------------------------------------------------------
getShapingDPI() const132     unsigned getShapingDPI() const                    { return m_shaping_dpi; }
133     // ------------------------------------------------------------------------
134     void shape(const std::u32string& text,
135                std::vector<irr::gui::GlyphLayout>& gls,
136                std::vector<std::u32string>* line_data = NULL);
137     // ------------------------------------------------------------------------
138     std::vector<irr::gui::GlyphLayout>& getCachedLayouts
139                   (const irr::core::stringw& str);
140     // ------------------------------------------------------------------------
clearCachedLayouts()141     void clearCachedLayouts()                         { m_cached_gls.clear(); }
142     // ------------------------------------------------------------------------
143     void initGlyphLayouts(const irr::core::stringw& text,
144                           std::vector<irr::gui::GlyphLayout>& gls,
145                           std::vector<std::u32string>* line_data = NULL);
146 #endif
147     // ------------------------------------------------------------------------
148     void loadFonts();
149     // ------------------------------------------------------------------------
150     void unitTesting();
151 
152 };   // FontManager
153 
154 extern FontManager *font_manager;
155 
156 #endif
157 /* EOF */
158