Gamedev Framework (gf)  0.3.0
A C++11 framework for 2D games
Font.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * Part of this file comes from SFML, with the same license:
22  * Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
23  */
24 #ifndef GF_FONT_H
25 #define GF_FONT_H
26 
27 #include <cstdint>
28 #include <map>
29 
30 #include "Filesystem.h"
31 #include "Portability.h"
32 #include "Texture.h"
33 
34 namespace gf {
35 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 inline namespace v1 {
37 #endif
38 
39  class InputStream;
40 
41  /**
42  * @ingroup graphics
43  * @brief A glyph
44  *
45  * A glyph is the visual representation of a character.
46  *
47  * Glyphs are loaded from fonts and put in a texture. In order to draw a
48  * glyph, you need to known the bounding rectangle of the glyph and the
49  * texture coordinates where the glyph is. Then, you can compute the
50  * position of the next glyph with the `advance` field.
51  *
52  * Generally, you do not have to manipulate glyphs directly. gf::Text
53  * can display text and make all the necessary computations for you.
54  *
55  * @sa gf::Font, gf::Text
56  */
57  struct GF_API Glyph {
58  RectF bounds; ///< Bouding rectangle of the glyph, in coordinates relative to the baseline
59  RectF textureRect; ///< Texture coordinates of the glyph inside the font's texture
60  float advance = 0.0f; ///< Offset to move horizontally to the next character
61  };
62 
63  /**
64  * @ingroup graphics
65  * @brief A character font
66  *
67  * Fonts can be loaded from a file, from memory or from a custom
68  * stream, and supports the most common types of fonts. See
69  * the `loadFromFile()` function for the complete list of supported formats.
70  *
71  * Once it is loaded, a gf::Font instance provides three
72  * types of information about the font:
73  *
74  * - Global metrics, such as the line spacing
75  * - Per-glyph metrics, such as bounding box or kerning
76  * - Pixel representation of glyphs
77  *
78  * Fonts alone are not very useful: they hold the font data
79  * but cannot make anything useful of it. To do so you need to
80  * use the gf::Text class, which is able to properly output text
81  * with several options such as character size, style, color,
82  * position, rotation, etc.
83  *
84  * This separation allows more flexibility and better performances:
85  * indeed a gf::Font is a heavy resource, and any operation on it
86  * is slow (often too slow for real-time applications). On the other
87  * side, a gf::Text is a lightweight object which can combine the
88  * glyphs data and metrics of a gf::Font to display any text on a
89  * render target.
90  *
91  * Note that it is also possible to bind several gf::Text instances
92  * to the same gf::Font.
93  *
94  * It is important to note that the gf::Text instance doesn't
95  * copy the font that it uses, it only keeps a reference to it.
96  * Thus, a gf::Font must not be destructed while it is
97  * used by a gf::Text (i.e. never write a function that
98  * uses a local gf::Font instance for creating a text).
99  *
100  * Usage example:
101  *
102  * ~~~{.cc}
103  * // Declare a new font
104  * gf::Font font;
105  *
106  * // Load it from a file
107  * if (!font.loadFromFile("arial.ttf"))
108  * {
109  * // error...
110  * }
111  *
112  * // Create a text which uses our font
113  * gf::Text text1;
114  * text1.setString("Hello World!")
115  * text1.setFont(font);
116  * text1.setCharacterSize(30);
117  *
118  * // Create another text using the same font, but with different parameters
119  * gf::Text text2;
120  * text2.setString("Goodbye world!");
121  * text2.setFont(font);
122  * text2.setCharacterSize(50);
123  * ~~~
124  *
125  * Apart from loading font files, and passing them to instances
126  * of gf::Text, you should normally not have to deal directly
127  * with this class. However, it may be useful to access the
128  * font metrics or rasterized glyphs for advanced usage.
129  */
130  class GF_API Font {
131  public:
132  /**
133  * @brief Default constructor
134  *
135  * This constructor defines an empty font.
136  */
137  Font();
138 
139  /**
140  * @brief Destructor
141  */
142  ~Font();
143 
144  /**
145  * @brief Deleted copy constructor
146  */
147  Font(const Font&) = delete;
148 
149  /**
150  * @brief Deleted copy assignement
151  */
152  Font& operator=(const Font&) = delete;
153 
154  /**
155  * @brief Move constructor
156  */
157  Font(Font&& other);
158 
159  /**
160  * @brief Move assignement
161  */
162  Font& operator=(Font&& other);
163 
164  /**
165  * @brief Load the font from a file
166  *
167  * The supported font formats are: TrueType, Type 1, CFF,
168  * OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
169  * Note that this function know nothing about the standard
170  * fonts installed on the user's system, thus you can't
171  * load them directly.
172  *
173  * @warning gf cannot preload all the font data in this
174  * function, so the file has to remain accessible until
175  * the gf::Font object loads a new font or is destroyed.
176  *
177  * @param filename Path of the font file to load
178  * @return True if loading succeeded, false if it failed
179  *
180  * @sa loadFromMemory(), loadFromStream()
181  */
182  bool loadFromFile(const Path& filename);
183 
184  /**
185  * @brief Load the font from a custom stream
186  *
187  * The supported font formats are: TrueType, Type 1, CFF,
188  * OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
189  *
190  * @warning gf cannot preload all the font data in this
191  * function, so the stream has to remain accessible until
192  * the gf::Font object loads a new font or is destroyed.
193  *
194  * @param stream Source stream to read from
195  * @return True if loading succeeded, false if it failed
196  *
197  * @sa loadFromFile(), loadFromMemory()
198  */
199  bool loadFromStream(InputStream& stream);
200 
201 
202  /**
203  * @brief Load the font from a file in memory
204  *
205  * The supported font formats are: TrueType, Type 1, CFF,
206  * OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
207  *
208  * @warning gf cannot preload all the font data in this
209  * function, so the stream has to remain accessible until
210  * the gf::Font object loads a new font or is destroyed.
211  *
212  * @param data Pointer to the file data in memory
213  * @param length Length of the data to load, in bytes
214  * @return True if loading succeeded, false if it failed
215  *
216  * @sa loadFromFile(), loadFromStream()
217  */
218  bool loadFromMemory(const uint8_t *data, std::size_t length);
219 
220 
221  /**
222  * @brief Retrieve a glyph of the font
223  *
224  * If the font is a bitmap font, not all character sizes
225  * might be available. If the glyph is not available at the
226  * requested size, an empty glyph is returned.
227  *
228  * @param codepoint Unicode code point of the character to get
229  * @param characterSize Reference character size
230  * @param outlineThickness Thickness of outline (when != 0 the glyph will not be filled)
231  *
232  * @return The corresponding glyph
233  */
234  const Glyph& getGlyph(char32_t codepoint, unsigned characterSize, float outlineThickness = 0.0f);
235 
236  /**
237  * @brief Get the kerning offset of two glyphs
238  *
239  * The kerning is an extra offset (negative) to apply between two
240  * glyphs when rendering them, to make the pair look more "natural".
241  * For example, the pair "AV" have a special kerning to make them
242  * closer than other characters. Most of the glyphs pairs have a
243  * kerning offset of zero, though.
244  *
245  * @param left Unicode code point of the left character
246  * @param right Unicode code point of the right character
247  * @param characterSize Reference character size
248  *
249  * @return Kerning value, in pixels
250  */
251  float getKerning(char32_t left, char32_t right, unsigned characterSize);
252 
253  /**
254  * @brief Get the line spacing
255  *
256  * Line spacing is the vertical offset to apply between two
257  * consecutive lines of text.
258  *
259  * @param characterSize Reference character size
260  *
261  * @return Line spacing, in pixels
262  */
263  float getLineSpacing(unsigned characterSize);
264 
265  /**
266  * @brief Retrieve the texture containing the loaded glyphs of a certain size
267  *
268  * The contents of the returned texture changes as more glyphs
269  * are requested, thus it is not very relevant. It is mainly
270  * used internally by gf::Text.
271  *
272  * @param characterSize Reference character size
273  *
274  * @return Texture containing the glyphs of the requested size
275  */
276  const AlphaTexture *getTexture(unsigned characterSize);
277 
278  /**
279  * @brief Generate the texture for a given character size
280  *
281  * After this call, the texture corresponding to the size is
282  * available through `getTexture`.
283  *
284  * @param characterSize Reference character size
285  */
286  void generateTexture(unsigned characterSize);
287 
288  private:
289  struct Packing {
290  unsigned top = 0;
291  unsigned bottom = 0;
292  unsigned right = 0;
293  };
294 
295  struct GlyphCache {
296  AlphaTexture texture;
297  std::map<uint64_t, Glyph> glyphs;
298  Packing packing;
299  };
300 
301  private:
302  GlyphCache createCache(unsigned characterSize);
303  Glyph createGlyph(char32_t codepoint, unsigned characterSize, float outlineThickness, GlyphCache& cache);
304 
305  bool setCurrentCharacterSize(unsigned characterSize);
306 
307  private:
308  void *m_library;
309  void *m_stroker;
310  void *m_face;
311  unsigned m_currentCharacterSize;
312  std::map<unsigned, GlyphCache> m_cache;
313  };
314 
315 #ifndef DOXYGEN_SHOULD_SKIP_THIS
316 }
317 #endif
318 }
319 
320 #endif // GF_FONT_H
A glyph.
Definition: Font.h:57
bool loadFromFile(const Path &filename)
Load the font from a file.
float getLineSpacing(unsigned characterSize)
Get the line spacing.
bool loadFromMemory(const uint8_t *data, std::size_t length)
Load the font from a file in memory.
~Font()
Destructor.
RectF bounds
Bouding rectangle of the glyph, in coordinates relative to the baseline.
Definition: Font.h:58
Font(Font &&other)
Move constructor.
float advance
Offset to move horizontally to the next character.
Definition: Font.h:60
Definition: Action.h:34
const Glyph & getGlyph(char32_t codepoint, unsigned characterSize, float outlineThickness=0.0f)
Retrieve a glyph of the font.
Abstract class for custom file input streams.
Definition: InputStream.h:51
A character font.
Definition: Font.h:130
RectF textureRect
Texture coordinates of the glyph inside the font's texture.
Definition: Font.h:59
Font()
Default constructor.
Font(const Font &)=delete
Deleted copy constructor.
Font & operator=(Font &&other)
Move assignement.
bool loadFromStream(InputStream &stream)
Load the font from a custom stream.
A texture with a single alpha channel.
Definition: Texture.h:474
#define GF_API
Definition: Portability.h:35
Font & operator=(const Font &)=delete
Deleted copy assignement.
const AlphaTexture * getTexture(unsigned characterSize)
Retrieve the texture containing the loaded glyphs of a certain size.
float getKerning(char32_t left, char32_t right, unsigned characterSize)
Get the kerning offset of two glyphs.
void generateTexture(unsigned characterSize)
Generate the texture for a given character size.