1 // -*- C++ -*-
2 /* GG is a GUI for OpenGL.
3    Copyright (C) 2003-2008 T. Zachary Laine
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public License
7    as published by the Free Software Foundation; either version 2.1
8    of the License, or (at your option) any later version.
9 
10    This library 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 GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA
19 
20    If you do not wish to comply with the terms of the LGPL please
21    contact the author as other terms are available for a fee.
22 
23    Zach Laine
24    whatwasthataddress@gmail.com */
25 
26 /** \file Font.h \brief Contains the Font class, a class that encapsulates the
27     rendering of a single FreeType-compatible font in italics, with
28     underlining, left-, right-, or center- justified, etc., and the
29     FontManager class which provides application-wide management of Font
30     objects. */
31 
32 #ifndef _GG_Font_h_
33 #define _GG_Font_h_
34 
35 #include <GG/AlignmentFlags.h>
36 #include <GG/FontFwd.h>
37 #include <GG/Texture.h>
38 #include <GG/UnicodeCharsets.h>
39 
40 #include <boost/graph/graph_concepts.hpp>
41 
42 #include <memory>
43 #include <set>
44 #include <stack>
45 #include <unordered_map>
46 
47 
48 struct FT_FaceRec_;
49 typedef struct FT_FaceRec_*  FT_Face;
50 typedef int FT_Error;
51 
52 namespace GG {
53 
54 class GLRGBAColorBuffer;
55 class GLTexCoordBuffer;
56 class GL2DVertexBuffer;
57 
58 /** Returns a string of the form "<rgba r g b a>" from a Clr object with color
59     channels r, b, g, a. */
60 GG_API std::string RgbaTag(const Clr& c);
61 
62 
63 /** \brief A bitmapped font rendering class.
64 
65     Font creates one or more 16-bits-per-pixel OpenGL textures that contain
66     rendered glyphs from a requested font file at the requested point size,
67     including only the requested ranges of code points.  Once the textures
68     have been created, text is rendered to the display by rendering quads
69     textured with portions of the glyph textures.  The glyphs are rendered to
70     the textures in white, with alpha blending used for antialiasing.  The
71     user should set the desired text color with a call to glColor*() before
72     any call to RenderText().  When text is rendered, DetermineLines() is
73     called to determine where the line breaks are, so that text can be
74     rendered centered, right-justified, or whatever.  To cut down on this
75     computation, when the text is not changing very rapidly (ie not every
76     frame), DetermineLines() can be called by the user once, and the result
77     supplied to RenderText() repeatedly.  When this is done, the iteration
78     through the text to determine line breaks is not necessary at render time.
79     The user is responsible for ensuring that the line data applies to the
80     text string supplied to RenderText().  See UnicodeCharsets.h for the
81     ranges of code points available, including a function that allow one to
82     determine which ranges are necessary for rendering a certain string.
83     Point sizes above 250 are not supported.  Note that users should not
84     normally need to use Font directly.  Users should instead use TextControl,
85     Edit, or MultiEdit.
86 
87     <h3>Text Formatting Tags</h3>
88 
89     GG::Font supports a few text formatting tags for convenience.  These tags
90     are similar to HTML or XML tags; there is an opening version "<tag>" and a
91     closing version "</tag>" of each tag.  Tags can be nested.  For instance,
92     consider the use of the italics tag \<i> here:
93 
94     \verbatim
95       <i>some text <i>and </i>some more </i>text \endverbatim
96 
97     In this example, everything is italicized except for "text".  Each \<i>
98     tag establishes that italics should be used for all further text until the
99     next \a matching \</i> tag.  The first \<i> tag matches the second \</i>
100     tag, and the two inner tags are matched.  Note that unmatched close-tags
101     (e.g. \</i>) are ignored by the text parser Font uses to find tags -- they
102     will appear as regular text.  The text justification tags are used on a
103     per-line basis, since it makes no sense to, for instance, right-justify
104     only a part of a line and center the rest. When more than one
105     justification tag appears on a line, the last one is used.  A
106     justification close-tag indicates that a line is to be the last one with
107     that justification, and only applies if that justification is active.
108 
109     <br>The supported tags are:
110     - \verbatim<i></i> \endverbatim                 Italics
111     - \verbatim<u></u> \endverbatim                 Underline
112     - \verbatim<s></s> \endverbatim                 Shadow
113     - \verbatim<rgba r g b a></rgba> \endverbatim   Color. Sets current rendering color to that specified by parameters.  Parameters may be either floating point values in the range [0.0, 1.0], or integer values in the range [0, 255].  All parameters must be in one format or the other.  The \</rgba> tag restores the previously set \<rgba> color, or restores the default color used to render the text when there are no other \<rgba> tags in effect.  Example tag: \<rgba 0.4 0.5 0.6 0.7>.
114     - \verbatim<left></left> \endverbatim           Left-justified text.
115     - \verbatim<center></center> \endverbatim       Centered text.
116     - \verbatim<right></right> \endverbatim         Right-justified text.
117     - \verbatim<pre></pre> \endverbatim             Preformatted.  Similar to HTML \<pre> tag, except this one only causes all tags to be ignored until a subsequent \</pre> tag is seen.  Note that due to their semantics, \<pre> tags cannot be nested.
118 
119     <p>Users of Font may wish to create their own tags as well.  Though Font
120     will know nothing about the semantics of the new tags, it is possible to
121     let Font know about them, in order for Font to render them invisible as it
122     does with the tags listed above.  See the static methods
123     RegisterKnownTag(), RemoveKnownTag(), and ClearKnownTags() for details.
124     It is not possible to remove the built-in tags using these methods.  If
125     you wish not to use tags at all, call DetermineLines() and RenderText()
126     with the format parameter containing FORMAT_IGNORETAGS, or include a
127     \<pre> tag at the beginning of the text to be rendered.
128    */
129 class GG_API Font
130 {
131 public:
132     /** \brief A range of iterators into a std::string that defines a
133         substring found in a string being rendered by Font.
134 
135         Substring is bound to a particular instance of a std::string.  If
136         that particular std::string goes out of scope or is deleted then
137         behavior is undefined, but may seg fault with the next access. */
138     class GG_API Substring
139     {
140     public:
141         typedef std::pair<std::string::const_iterator, std::string::const_iterator> IterPair;
142 
143         Substring();
144 
145         /** Ctor.  \a first_ must be <= \a second_. */
146         Substring(const std::string& str_,
147                   std::string::const_iterator first_,
148                   std::string::const_iterator second_);
149 
150         /** Construction from base.  \a pair.first must be <= \a
151             pair.second. */
152         Substring(const std::string& str_, const IterPair& pair);
153 
154         /** Attach this Substring to \p str_.
155 
156             This changes the iterators from pointing into the previous
157             std::string to pointing into \p str_.
158         */
159         void Bind(const std::string& str_);
160 
161         /** Returns an iterator to the beginning of the substring. */
162         std::string::const_iterator begin() const;
163 
164         /** Returns an iterator to one-past-the-end of the substring. */
165         std::string::const_iterator end() const;
166 
167         /** True iff .first == .second. */
168         bool empty() const;
169 
170         /** Length, in original string chars, of the substring. */
171         std::size_t size() const;
172 
173         /** Implicit conversion to std::string. */
174         operator std::string() const;
175 
176         /** Comparison with std::string. */
177         bool operator==(const std::string& rhs) const;
178 
179         /** Comparison with std::string. */
180         bool operator!=(const std::string& rhs) const;
181 
182         /** Concatenation with base.  \a rhs.first must be <= \a rhs.second.
183             .second must be equal to \a rhs.first (*this and \a rhs must be
184             contiguous). */
185         Substring& operator+=(const IterPair& rhs);
186 
187     private:
188         const std::string* str;
189         std::ptrdiff_t first;
190         std::ptrdiff_t second;
191 
192         static const std::string EMPTY_STRING;
193     };
194 
195     /** \brief Used to encapsulate a token-like piece of text to be rendered
196         using GG::Font. */
197     struct GG_API TextElement
198     {
199         /** The types of token-like entities that can be represented by a
200             TextElement. */
201         enum TextElementType {
202             OPEN_TAG,   ///< An opening text formatting tag (e.g. "<rgba 0 0 0 255>").
203             CLOSE_TAG,  ///< A closing text formatting tag (e.g. "</rgba>").
204             TEXT,       ///< Some non-whitespace text (e.g. "The").
205             WHITESPACE, ///< Some whitespace text (e.g. "  \n").
206 
207             /** A newline.  Newline TextElements represent the newline code
208                 point when it is encountered in a rendered string, though they
209                 do not contain the actual newline character -- their \a text
210                 members are always ""). */
211             NEWLINE
212         };
213 
214         /** Ctor.  \a ws indicates that the element contains only whitespace;
215             \a nl indicates that it is a newline element. */
216         TextElement(bool ws, bool nl);
217 
218         virtual ~TextElement();
219 
220         /** Attach this TextElement to the string \p whole_text, by
221             attaching the SubString data member text to \p whole_text.
222 
223             Binding to a new \p whole_text is very fast compared to
224             re-parsing the entire \p whole_text and allows TextElements of
225             TextElementType TEXT to be changed quickly if it is known that
226             the parse would be the same.
227 
228             It is efficient when you want to do a text parse or layout
229             once, and then create several different controls that have the
230             same text layout and text contents, but each of them needs to
231             keep there own internal copy of the text. So, while the pointer
232             diffs are all the same, since the text contents are the same,
233             the pointer to the string in each TextElement (and its
234             contained Substring) needs to be set to the appropriate copy of
235             the string.
236 
237             This is used in TextControl and its derived classes to re-use
238             entire vectors of TextElement with different std::strings
239             without re-parsing the std::string.
240          */
241         virtual void Bind(const std::string& whole_text);
242 
243         /** Returns the TextElementType of the element. */
244         virtual TextElementType Type() const;
245 
246         /** Returns the width of the element. */
247         X Width() const;
248 
249         /* Returns the number of characters in the original string that the
250            element represents. */
251         StrSize StringSize() const;
252 
253         /** Returns the number of code points in the original string that the
254             element represents. */
255         CPSize CodePointSize() const;
256 
257         virtual bool operator==(const TextElement &rhs) const;
258 
259         /** The text from the original string represented by the element. */
260         Substring text;
261 
262         std::vector<X> widths;     ///< The widths of the glyphs in \a text.
263         const bool     whitespace; ///< True iff this is a whitespace element.
264         const bool     newline;    ///< True iff this is a newline element.
265 
266     protected:
267         TextElement();
268 
269     private:
270         mutable X cached_width;
271     };
272 
273     /** \brief TextAndElementsAssembler is used to assemble a matched pair of text and a vector of
274         TextElement, without incurring the computational cost of parsing the text with
275         ExpensiveParseFromTextToTextElements().
276 
277         The pair of string and vector returned by Text() and Elements() are consistent with each
278         other and can be used with the fast constructor or the fast SetText variant of TextControl.
279     */
280     class GG_API TextAndElementsAssembler
281     {
282     public:
283         TextAndElementsAssembler(const Font& font);
284         ~TextAndElementsAssembler();
285 
286         /** Return the constructed text.*/
287         const std::string& Text();
288         /** Return the constructed TextElements.*/
289         const std::vector<std::shared_ptr<TextElement>>& Elements();
290 
291         /** Add an open tag iff it exists as a recognized tag.*/
292         TextAndElementsAssembler& AddOpenTag(const std::string& tag);
293         /** Add an open tag iff it exists as a recognized tag.*/
294         TextAndElementsAssembler& AddOpenTag(const std::string& tag, const std::vector<std::string>& params);
295         /** Add a close tag iff it exists as a recognized tag.*/
296         TextAndElementsAssembler& AddCloseTag(const std::string& tag);
297         /** Add a text element.  Any whitespace in this text element will be non-breaking.*/
298         TextAndElementsAssembler& AddText(const std::string& text);
299         /** Add a white space element.*/
300         TextAndElementsAssembler& AddWhitespace(const std::string& whitespace);
301         /** Add a new line element.*/
302         TextAndElementsAssembler& AddNewline();
303 
304         /** Add an open Clr tag.*/
305         TextAndElementsAssembler& AddOpenTag(const Clr& color);
306 
307     private:
308         class Impl;
309         std::unique_ptr<Impl> const m_impl;
310     };
311 
312     /** \brief The type of TextElement that represents a text formatting
313         tag. */
314     struct GG_API FormattingTag : TextElement
315     {
316         /** Ctor.  \a close indicates that the tag is a close-tag
317             (e.g. "</rgba>"). */
318         FormattingTag(bool close);
319 
320         /** Attach to \p whole_text by binding all Substring data members,
321             both the base class and the data member tag_name to the string
322             \p whole_text.*/
323         void Bind(const std::string& whole_text) override;
324 
325         TextElementType Type() const override;
326 
327         bool operator==(const TextElement &rhs) const override;
328 
329         /** The parameter strings within the tag, e.g. "0", "0", "0", and "255"
330             for the tag "<rgba 0 0 0 255>". */
331         std::vector<Substring> params;
332 
333         /** The name of the tag (e.g. for the tag "<i>", tag_name is "i"). */
334         Substring tag_name;
335 
336         /** True iff this is a close-tag. */
337         const bool close_tag;
338 
339     private:
340         FormattingTag();
341     };
342 
343     /** \brief Holds the essential data on each line that a string occupies when
344         rendered with given format flags.
345 
346         \a char_data contains the visible glyphs for each line, plus any text
347         formatting tags present on that line as well. */
348     struct GG_API LineData
349     {
350         LineData();
351 
352         /** \brief Contains the extent, the index into the original string,
353             and the text formatting tags that should be applied before
354             rendering of a visible glyph. */
355         struct GG_API CharData
356         {
357             CharData();
358 
359             CharData(X extent_, StrSize str_index, StrSize str_size, CPSize cp_index,
360                      const std::vector<std::shared_ptr<TextElement>>& tags_);
361 
362             /** The furthest-right extent of this glyph as it appears on the
363                 line. */
364             X extent;
365 
366             /** The position in the original string of the first character of
367                 this glyph. */
368             StrSize string_index;
369 
370             /** The size in the original string of the characters that make up
371                 this glyph. */
372             StrSize string_size;
373 
374             /** The code point index of this glyph. */
375             CPSize code_point_index;
376 
377             /** The text formatting tags that should be applied before
378                 rendering this glyph. */
379             std::vector<std::shared_ptr<FormattingTag>> tags;
380         };
381 
382         X    Width() const; ///< Returns the width of the line.
383         bool Empty() const; ///< Returns true iff char_data has size 0.
384 
385         /** Data on each individual glyph. */
386         std::vector<CharData> char_data;
387 
388         /** FORMAT_LEFT, FORMAT_CENTER, or FORMAT_RIGHT; derived from text
389             format flags and/or formatting tags in the text. */
390         Alignment justification;
391     };
392 
393     /** \brief Holds the state of tags during rendering of text.
394 
395         By keeping track of this state across multiple calls to RenderText(),
396         the user can preserve the functionality of the text formatting tags,
397         if present. */
398     struct GG_API RenderState
399     {
400         RenderState();
401 
402         RenderState(Clr color); //< Takes default text color as parameter
403 
404         /** The count of open \<i> tags seen since the last \</i> seen. */
405         std::size_t     use_italics;
406 
407         /** The count of open \<s> tags seen since the last \</s> seen. */
408         std::size_t     use_shadow;
409 
410         /** The count of open \<u> tags seen since the last \</u> seen. */
411         std::size_t     draw_underline;
412 
413         /** The count of open \<super> (positive) minus \<sub> tags seen. */
414         int             super_sub_shift;
415 
416         /** The stack of text color indexes (as set by previous tags). */
417         std::stack<int> color_index_stack;
418 
419         /** All colors that have been used. **/
420         std::vector<Clr> used_colors;
421 
422         /// Add color to stack and remember it has been used
423         void PushColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a);
424 
425         /// Return to the previous used color, or remain as default
426         void PopColor();
427 
428         /// Return the index of the current color in used_colors
429         int CurrentIndex() const;
430 
431         const Clr& CurrentColor()  const;
432 
433         /// Return true if there are no more colors to pop.
434         bool ColorsEmpty() const;
435     };
436 
437     /** \brief Holds precomputed glyph position information for rendering.
438      */
439     struct RenderCache
440     {
441         std::unique_ptr<GL2DVertexBuffer> vertices;
442         std::unique_ptr<GLTexCoordBuffer> coordinates;
443         std::unique_ptr<GLRGBAColorBuffer> colors;
444 
445         std::unique_ptr<GL2DVertexBuffer> underline_vertices;
446         std::unique_ptr<GLRGBAColorBuffer> underline_colors;
447 
448         RenderCache();
449 
450         ~RenderCache();
451     };
452 
453     /** \name Structors */ ///@{
454     /** Ctor.  Construct a font using only the printable ASCII characters.
455         \throw Font::Exception Throws a subclass of Font::Exception if the
456         condition specified for the subclass is met. */
457     Font(const std::string& font_filename, unsigned int pts);
458 
459     /** Ctor.  Construct a font using only the printable ASCII characters,
460         from the in-memory contents \a file_contents.  \throw Font::Exception
461         Throws a subclass of Font::Exception if the condition specified for
462         the subclass is met. */
463     Font(const std::string& font_filename, unsigned int pts,
464          const std::vector<unsigned char>& file_contents);
465 
466     /** Ctor.  Construct a font using all the code points in the
467         UnicodeCharsets in the range [first, last).  \throw Font::Exception
468         Throws a subclass of Font::Exception if the condition specified for
469         the subclass is met. */
470     template <typename CharSetIter>
471     Font(const std::string& font_filename, unsigned int pts,
472          CharSetIter first, CharSetIter last);
473 
474     /** Ctor.  Construct a font using all the code points in the
475         UnicodeCharsets in the range [first, last), from the in-memory
476         contents \a file_contents.  \throw Font::Exception Throws a subclass
477         of Font::Exception if the condition specified for the subclass is
478         met. */
479     template <typename CharSetIter>
480     Font(const std::string& font_filename, unsigned int pts,
481          const std::vector<unsigned char>& file_contents,
482          CharSetIter first, CharSetIter last);
483 
484     ~Font(); ///< Dtor.
485     //@}
486 
487     /** \name Accessors */ ///@{
488     /** Returns the name of the file from which this font was created. */
489     const std::string& FontName() const;
490 
491     /** Returns the point size in which the characters in the font object are
492         rendered. */
493     unsigned int PointSize() const;
494 
GetTexture()495     const std::shared_ptr<Texture> GetTexture() const
496     { return m_texture; }
497 
498     /** Returns the range(s) of code points rendered in the font */
499     const std::vector<UnicodeCharset>& UnicodeCharsets() const;
500 
501     /** Returns the maximum amount above the baseline the text can go. */
502     Y    Ascent() const;
503 
504     /** Returns the maximum amount below the baseline the text can go. */
505     Y    Descent() const;
506 
507     /** Returns (Ascent() - Descent()). */
508     Y    Height() const;
509 
510     /** Returns the distance that should be placed between lines.  This is
511         usually not equal to Height(). */
512     Y    Lineskip() const;
513 
514     /** Returns the width of the glyph for the space character. */
515     X    SpaceWidth() const;
516 
517     /** Unformatted text rendering; repeatedly calls RenderGlyph, then returns
518         advance of entire string. */
519     X    RenderText(const Pt& pt, const std::string& text) const;
520 
521     /** Formatted text rendering. */
522     void RenderText(const Pt& pt1, const Pt& pt2, const std::string& text, Flags<TextFormat>& format,
523                     const std::vector<LineData>& line_data, RenderState* render_state = nullptr) const;
524 
525     /** Formatted text rendering over a subset of lines and code points.  The
526         glyphs rendered are in the range [CodePointIndexOf(<i>begin_line</i>,
527         <i>begin_char</i>, <i>line_data</i>), CodePointIndexOf(<i>end_line</i> -
528         1, <i>end_char</i>, <i>line_data</i>)). */
529     void RenderText(const Pt& pt1, const Pt& pt2, const std::string& text, Flags<TextFormat>& format,
530                     const std::vector<LineData>& line_data, RenderState& render_state,
531                     std::size_t begin_line, CPSize begin_char,
532                     std::size_t end_line, CPSize end_char) const;
533 
534     /** Wrapper around PreRenderText that provides dummy values for line start and end values.*/
535     void PreRenderText(const Pt& ul, const Pt& lr, const std::string& text, Flags<TextFormat>& format,
536                        RenderCache& cache, const std::vector<LineData>& line_data,
537                        RenderState* render_state = nullptr) const;
538 
539     /** Fill the \p cache with glyphs corresponding to the passed in \p text and \p line_data.*/
540     void PreRenderText(const Pt& pt1, const Pt& pt2, const std::string& text,
541                        Flags<TextFormat>& format, const std::vector<LineData>& line_data,
542                        RenderState& render_state, std::size_t begin_line, CPSize begin_char,
543                        std::size_t end_line, CPSize end_char, RenderCache& cache) const;
544 
545     /** Render the glyphs from the \p cache.*/
546     void RenderCachedText(RenderCache& cache) const;
547 
548     /** Sets \a render_state as if all the text before (<i>begin_line</i>,
549         <i>begin_char</i>) had just been rendered. */
550     void ProcessTagsBefore(const std::vector<LineData>& line_data, RenderState& render_state,
551                            std::size_t begin_line, CPSize begin_char) const;
552 
553     /** Return a vector of TextElements parsed from \p text, using the
554         FORMAT_IGNORETAGS bit in \p format to determine if all KnownTags()
555         are ignored.
556 
557         This function is costly even on single character texts. Do not call
558         it from tight loops.  Do not call it from within Render().  Do not
559         call it repeatedly on a known text.
560     */
561     std::vector<std::shared_ptr<Font::TextElement>> ExpensiveParseFromTextToTextElements(const std::string& text,
562                                                                                          const Flags<TextFormat>& format) const;
563 
564     /** Fill \p text_elements with the font widths of characters from \p text starting from \p
565         starting_from. */
566     void FillTemplatedText(const std::string& text,
567                            std::vector<std::shared_ptr<TextElement>>& text_elements,
568                            std::vector<std::shared_ptr<TextElement>>::iterator starting_from) const;
569 
570     /** Change \p text_elements and \p text to replace the text of the TextElement at
571         \p targ_offset with \p new_text.
572 
573         This replaces the entire text of the TextElement at offset \p targ_offset and adjusts the
574         string \p text to be consistent even if the \p new_text is longer/shorter than the original
575         TEXT type TextElement.
576 
577         This does not recompute the text_elements. It is faster than
578         ExpensiveParseFromTextToTextElements on a new string. It will not find white space in the
579         inserted text.
580 
581         \p text and \p text_elements are assumed to be consistent with each other and both will be
582         changed to remain consistent.
583 
584         \p targ_offset is the zero based offset of the TextElements of type TEXT.  It ignores
585         other types of TextElements such as TAGS, WHITESPACE and NEWLINE, when determining the
586         offset.
587 
588         Here is an example of changing a ship name from "oldname" to "New Ship Name":
589 
590         original text:             "<i>Ship:<\i> oldname ID:"
591         orignal text_elements:     [<OPEN_TAG i>, <TEXT "Ship:">, <CLOSE_TAG i>, <WHITESPACE>, <TEXT oldname>, <WHITESPACE>, <TEXT ID:>]
592 
593         ChangeTemplatedText(text, text_elements, "New Ship Name", 1);
594 
595         changed text:              "<i>Ship:<\i> New Ship Name ID:"
596         changed text_elements:     [<OPEN_TAG i>, <TEXT "Ship:">, <CLOSE_TAG i>, <WHITESPACE>, <TEXT New Ship Name>, <WHITESPACE>, <TEXT ID:>]
597 
598     */
599     void ChangeTemplatedText(std::string& text,
600                              std::vector<std::shared_ptr<TextElement>>& text_elements,
601                              const std::string& new_text,
602                              size_t targ_offset) const;
603 
604     /** DetermineLines() returns the \p line_data resulting from adding the necessary line
605         breaks, to  the \p text formatted with \p format and parsed into \p text_elements, to fit
606         the \p text into a box of width \p box_width.
607 
608         It accounts for alignment, wrapping and justification of the \p text.
609 
610         A \p box_width of X0 will add a line break at every whitespace element in \p text_elements.
611 
612         Supplying a \p text and \p text_elements that are incompatible will result in undefined
613         behavior.  \p text_elements contains internal pointers to the \p text to which it is
614         bound.  Compatible means the exact same \p text object, not the same text content.
615         */
616     std::vector<LineData>   DetermineLines(const std::string& text, Flags<TextFormat>& format, X box_width,
617                                            const std::vector<std::shared_ptr<TextElement>>& text_elements) const;
618 
619     /** Returns the maximum dimensions of the text in x and y. */
620     Pt   TextExtent(const std::vector<LineData>& line_data) const;
621     //@}
622 
623     /** Adds \a tag to the list of embedded tags that Font should not print
624         when rendering text.  Passing "foo" will cause Font to treat "<foo>",
625         "<foo [arg1 [arg2 ...]]>", and "</foo>" as tags. */
626     static void RegisterKnownTag(const std::string& tag);
627 
628     /** Removes \a tag from the known tag list.  Does not remove the built in
629         tags: \<i>, \<u>, \<rgba r g b a>, and \<pre>. */
630     static void RemoveKnownTag(const std::string& tag);
631 
632     /** Removes all tags from the known tag list.  Does not remove the built
633         in tags: \<i>, \<u>, \<rgba r g b a>, and \<pre>. */
634     static void ClearKnownTags();
635 
636     /** Returns the input \a text, stripped of any formatting tags. */
637     static std::string StripTags(const std::string& text, bool strip_unpaired_tags = true);
638 
639     /** \name Exceptions */ ///@{
640     /** The base class for Font exceptions. */
641     GG_ABSTRACT_EXCEPTION(Exception);
642 
643     /** Thrown when valid font data cannot be read from a file. */
644     GG_CONCRETE_EXCEPTION(BadFile, GG::Font, Exception);
645 
646     /** Thrown when a 0 font size is requested. */
647     GG_CONCRETE_EXCEPTION(InvalidPointSize, GG::Font, Exception);
648 
649     /** Thrown when a FreeType font could be loaded, but the resulting font is
650         not scalable, making it unusable by GG. */
651     GG_CONCRETE_EXCEPTION(UnscalableFont, GG::Font, Exception);
652 
653     /** Thrown when an attempt is made to create a glyph from null font face
654         object. */
655     GG_CONCRETE_EXCEPTION(BadFace, GG::Font, Exception);
656 
657     /** Thrown when an attempt to set the size of a FreeType font face
658         fails. */
659     GG_CONCRETE_EXCEPTION(BadPointSize, GG::Font, Exception);
660 
661     /** Thrown when FreeType is unable to fulfill a request to load or render
662         a glpyh. */
663     GG_CONCRETE_EXCEPTION(BadGlyph, GG::Font, Exception);
664     //@}
665 
666     /** Throws a BadGlyph exception, with \a c converted to a printable ASCII
667         character (if possible), or as a Unicode code point.  \a format_str
668         should contain the Boost.Format positional notation formatting tag
669         "%1%" where the code point should appear. */
670     static void ThrowBadGlyph(const std::string& format_str, std::uint32_t c);
671 
672 protected:
673     /** \name Structors */ ///@{
674     Font();
675     //@}
676 
677 private:
678     /** \brief This just holds the essential data necessary to render a glyph
679         from the OpenGL texture(s) created at GG::Font creation time. */
680     struct Glyph
681     {
682         Glyph();
683 
684         Glyph(const std::shared_ptr<Texture>& texture, const Pt& ul, const Pt& lr, Y y_ofs,
685               X lb, X adv); ///< Ctor
686 
687         SubTexture  sub_texture;   ///< The subtexture containing just this glyph
688         Y           y_offset;      ///< The vertical offset to draw this glyph (may be negative!)
689         X           left_bearing;  ///< The space that should remain before the glyph
690         X           advance;       ///< The amount of space the glyph should occupy, including glyph graphic and inter-glyph spacing
691         X           width;         ///< The width of the glyph only
692     };
693 
694     typedef std::unordered_map<std::uint32_t, Glyph> GlyphMap;
695 
696     FT_Error          GetFace(FT_Face& face);
697     FT_Error          GetFace(const std::vector<unsigned char>& file_contents, FT_Face& face);
698     void              CheckFace(FT_Face font, FT_Error error);
699     void              Init(FT_Face& font);
700 
701     bool GenerateGlyph(FT_Face font, std::uint32_t ch);
702 
703     void              ValidateFormat(Flags<TextFormat>& format) const;
704 
705     X                 StoreGlyph(const Pt& pt, const Glyph& glyph, const RenderState* render_state,
706                                  RenderCache& cache) const;
707     void              StoreGlyphImpl(RenderCache& cache, GG::Clr color, const Pt& pt,
708                                      const Glyph& glyph, int x_top_offset,
709                                      int y_shift) const;
710     void              StoreUnderlineImpl(RenderCache& cache, GG::Clr color, const Pt& pt,
711                                          const Glyph& glyph, Y descent, Y height,
712                                          Y underline_height, Y underline_offset) const;
713 
714     void              HandleTag(const std::shared_ptr<FormattingTag>& tag, double* orig_color,
715                                 RenderState& render_state) const;
716     bool              IsDefaultFont();
717 
718     std::shared_ptr<Font> GetDefaultFont(unsigned int pts);
719 
720     std::string          m_font_filename;
721     unsigned int         m_pt_sz;
722     std::vector<UnicodeCharset>
723                          m_charsets;    ///< The sets of glyphs that are covered by this font object
724     Y                    m_ascent;      ///< Maximum amount above the baseline the text can go
725     Y                    m_descent;     ///< Maximum amount below the baseline the text can go
726     Y                    m_height;      ///< Ascent - descent
727     Y                    m_lineskip;    ///< Distance that should be placed between lines
728     double               m_underline_offset; ///< Amount below the baseline that the underline sits
729     double               m_underline_height; ///< Height (thickness) of underline
730     double               m_italics_offset;   ///< Amount that the top of an italicized glyph is left of the bottom
731     double               m_super_sub_offset; ///< Ammount to shift super or subscript text
732     double               m_shadow_offset;    ///< Amount that shadows rendered under texts are displaced from the text
733     X                    m_space_width; ///< The width of the glyph for the space character
734     GlyphMap             m_glyphs;      ///< The locations of the images of each glyph within the textures
735 
736     /** The OpenGL texture object in which the glyphs can be found. */
737     std::shared_ptr<Texture> m_texture;
738 };
739 
740 /** Stream output operator for Font::Substring. */
741 GG_API std::ostream& operator<<(std::ostream& os, const Font::Substring& substr);
742 
743 /** Returns the code point index of the <i>index</i>-th code point on line \a
744     line within the text represented by \a line_data.  Returns the index of
745     the code point one past the end of the text if \a line or \a index are out
746     of bounds. */
747 GG_API CPSize CodePointIndexOf(std::size_t line, CPSize index,
748                                const std::vector<Font::LineData>& line_data);
749 
750 /** Returns the string index of the <i>index</i>-th code point on line \a line
751     within the text represented by \a line_data.  Returns the index of the
752     character one past the end of the text if \a line or \a index are out of
753     bounds. */
754 GG_API StrSize StringIndexOf(std::size_t line, CPSize index,
755                              const std::vector<Font::LineData>& line_data);
756 
757 /** Returns the line L and the code point index within L of the
758     <i>index</i>-th code point within the text represented by \a line_data.
759     Returns (std::numeric_limits<std::size_t>::max(), INVALID_CP_SIZE) if \a
760     index is out of bounds. */
761 GG_API std::pair<std::size_t, CPSize>
762 LinePositionOf(CPSize index, const std::vector<Font::LineData>& line_data);
763 
764 
765 /** \brief A singleton that loads and stores fonts for use by GG.
766 
767     This class is essentially a very thin wrapper around a map of
768     Font smart pointers, keyed on font filename/point size pairs.  The user
769     need only request a font through GetFont(); if the font at the requested
770     size needs to be created, the font is created at the requestd size, a
771     shared_ptr to it is kept, and a copy of the shared_ptr is returned.  If
772     the font has been created at the desired size, but the request includes
773     code point range(s) not already created, the font at the requested size is
774     created with the union of the reqested and existing ranges, stored, and
775     returned as above; the only difference is that the original shared_ptr is
776     released.  Due to the shared_ptr semantics, the object pointed to by the
777     shared_ptr is deleted if and only if the last shared_ptr that refers to it
778     is deleted.  So any requested font can be used as long as the caller
779     desires, even when another caller tells the FontManager to free the
780     font. */
781 class GG_API FontManager
782 {
783 private:
784     /** \brief This GG::FontManager-private struct is used as a key type for
785         the map of rendered fonts. */
786     struct GG_API FontKey
787     {
788         FontKey(const std::string& str, unsigned int pts); ///< Ctor.
789         bool operator<(const FontKey& rhs) const; ///< Lexocograhpical ordering on filename then points.
790 
791         std::string  filename; ///< The name of the file from which this font was created.
792         unsigned int points;   ///< The point size in which this font was rendered.
793     };
794 
795 public:
796     /** \name Accessors */ ///@{
797     /** Returns true iff this manager contains a font with the given filename
798         and point size, regardless of charsets. */
799     bool HasFont(const std::string& font_filename, unsigned int pts) const;
800 
801     /** Returns true iff this manager contains a font with the given filename
802         and point size, containing the given charsets. */
803     template <typename CharSetIter>
804     bool HasFont(const std::string& font_filename, unsigned int pts,
805                  CharSetIter first, CharSetIter last) const;
806     //@}
807 
808     /** \name Mutators */ ///@{
809     /** Returns a shared_ptr to the requested font, supporting all printable
810         ASCII characters.  \note May load font if unavailable at time of
811         request. */
812     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts);
813 
814     /** Returns a shared_ptr to the requested font, supporting all printable
815         ASCII characters, from the in-memory contents \a file_contents.  \note
816         May load font if unavailable at time of request. */
817     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts,
818                                   const std::vector<unsigned char>& file_contents);
819 
820     /** Returns a shared_ptr to the requested font, supporting all the
821         code points in the UnicodeCharsets in the range [first, last).  \note
822         May load font if unavailable at time of request. */
823     template <typename CharSetIter>
824     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts,
825                                   CharSetIter first, CharSetIter last);
826 
827     /** Returns a shared_ptr to the requested font, supporting all the code
828         points in the UnicodeCharsets in the range [first, last), from the
829         in-memory contents \a file_contents.  \note May load font if
830         unavailable at time of request. */
831     template <typename CharSetIter>
832     std::shared_ptr<Font> GetFont(const std::string& font_filename, unsigned int pts,
833                                   const std::vector<unsigned char>& file_contents,
834                                   CharSetIter first, CharSetIter last);
835 
836     /** Removes the indicated font from the font manager.  Due to shared_ptr
837         semantics, the font may not be deleted until much later. */
838     void                    FreeFont(const std::string& font_filename, unsigned int pts);
839     //@}
840 
841 private:
842     FontManager();
843     template <typename CharSetIter>
844     std::shared_ptr<Font> GetFontImpl(const std::string& font_filename, unsigned int pts,
845                                       const std::vector<unsigned char>* file_contents,
846                                       CharSetIter first, CharSetIter last);
847 
848     std::map<FontKey, std::shared_ptr<Font>> m_rendered_fonts;
849 
850     static const std::shared_ptr<Font> EMPTY_FONT;
851 
852     friend GG_API FontManager& GetFontManager();
853 };
854 
855 /** Returns the singleton FontManager instance. */
856 GG_API FontManager& GetFontManager();
857 
858 /** Thrown when initialization of the FreeType library fails. */
859 GG_EXCEPTION(FailedFTLibraryInit);
860 
861 namespace detail {
862     template <typename CharT, bool CharIsSigned = boost::is_signed<CharT>::value>
863     struct ValidUTFChar;
864 
865     template <typename CharT>
866     struct ValidUTFChar<CharT, true>
867     {
868         bool operator()(CharT c)
869             { return 0x0 <= c; }
870     };
871 
872     template <typename CharT>
873     struct ValidUTFChar<CharT, false>
874     {
875         bool operator()(CharT c)
876             { return c <= 0x7f; }
877     };
878 
879     struct GG_API FTFaceWrapper
880     {
881         FTFaceWrapper();
882         ~FTFaceWrapper();
883         FT_Face m_face = nullptr;
884     };
885 }
886 
887 } // namespace GG
888 
889 
890 // template implementations
891 template <typename CharSetIter>
892 GG::Font::Font(const std::string& font_filename, unsigned int pts,
893                CharSetIter first, CharSetIter last) :
894     m_font_filename(font_filename),
895     m_pt_sz(pts),
896     m_charsets(first, last),
897     m_ascent(0),
898     m_descent(0),
899     m_height(0),
900     m_lineskip(0),
901     m_underline_offset(0.0),
902     m_underline_height(0.0),
903     m_italics_offset(0.0),
904     m_super_sub_offset(0.0),
905     m_shadow_offset(0.0),
906     m_space_width(0)
907 {
908     if (!m_font_filename.empty()) {
909         detail::FTFaceWrapper wrapper;
910         FT_Error error = GetFace(wrapper.m_face);
911         CheckFace(wrapper.m_face, error);
912         Init(wrapper.m_face);
913     }
914 }
915 
916 template <typename CharSetIter>
917 GG::Font::Font(const std::string& font_filename, unsigned int pts,
918                const std::vector<unsigned char>& file_contents,
919                CharSetIter first, CharSetIter last) :
920     m_font_filename(font_filename),
921     m_pt_sz(pts),
922     m_charsets(first, last),
923     m_ascent(0),
924     m_descent(0),
925     m_height(0),
926     m_lineskip(0),
927     m_underline_offset(0.0),
928     m_underline_height(0.0),
929     m_italics_offset(0.0),
930     m_super_sub_offset(0.0),
931     m_shadow_offset(0.0),
932     m_space_width(0)
933 {
934     assert(!file_contents.empty());
935     detail::FTFaceWrapper wrapper;
936     FT_Error error = GetFace(file_contents, wrapper.m_face);
937     CheckFace(wrapper.m_face, error);
938     Init(wrapper.m_face);
939 }
940 
941 template <typename CharSetIter>
942 bool GG::FontManager::HasFont(const std::string& font_filename, unsigned int pts,
943                               CharSetIter first, CharSetIter last) const
944 {
945     bool retval = false;
946     FontKey key(font_filename, pts);
947     auto it = m_rendered_fonts.find(key);
948     if (it != m_rendered_fonts.end()) {
949         std::set<UnicodeCharset> requested_charsets(first, last);
950         std::set<UnicodeCharset> found_charsets(it->second->UnicodeCharsets().begin(),
951                                                 it->second->UnicodeCharsets().end());
952         retval = requested_charsets == found_charsets;
953     }
954     return retval;
955 }
956 
957 template <typename CharSetIter>
958 std::shared_ptr<GG::Font>
959 GG::FontManager::GetFont(const std::string& font_filename, unsigned int pts,
960                          CharSetIter first, CharSetIter last)
961 { return GetFontImpl(font_filename, pts, nullptr, first, last); }
962 
963 template <typename CharSetIter>
964 std::shared_ptr<GG::Font>
965 GG::FontManager::GetFont(const std::string& font_filename, unsigned int pts,
966                          const std::vector<unsigned char>& file_contents,
967                          CharSetIter first, CharSetIter last)
968 { return GetFontImpl(font_filename, pts, &file_contents, first, last); }
969 
970 
971 template <typename CharSetIter>
972 std::shared_ptr<GG::Font>
973 GG::FontManager::GetFontImpl(const std::string& font_filename, unsigned int pts,
974                              const std::vector<unsigned char>* file_contents,
975                              CharSetIter first, CharSetIter last)
976 {
977     FontKey key(font_filename, pts);
978     auto it = m_rendered_fonts.find(key);
979     if (it == m_rendered_fonts.end()) { // if no such font has been created, create it now
980         if (font_filename.empty()) {
981             // keeps this function from throwing; "" is the only invalid font
982             // filename that shouldn't throw
983             return EMPTY_FONT;
984         } else {
985             std::shared_ptr<Font> font(
986                 file_contents ?
987                 new Font(font_filename, pts, *file_contents, first, last) :
988                 new Font(font_filename, pts, first, last)
989             );
990             m_rendered_fonts[key] = font;
991             return m_rendered_fonts[key];
992         }
993     // if a font like this has been created, but it doesn't have all the right
994     // glyphs, release it and create a new one
995     } else {
996         std::set<UnicodeCharset> requested_charsets(first, last);
997         std::set<UnicodeCharset> found_charsets(it->second->UnicodeCharsets().begin(),
998                                                 it->second->UnicodeCharsets().end());
999         if (requested_charsets != found_charsets) {
1000             std::vector<UnicodeCharset> united_charsets;
1001             std::set_union(requested_charsets.begin(), requested_charsets.end(),
1002                            found_charsets.begin(), found_charsets.end(),
1003                            std::back_inserter(united_charsets));
1004             m_rendered_fonts.erase(it);
1005             std::shared_ptr<Font> font(
1006                 file_contents ?
1007                 new Font(font_filename, pts, *file_contents,
1008                          united_charsets.begin(), united_charsets.end()) :
1009                 new Font(font_filename, pts,
1010                          united_charsets.begin(), united_charsets.end())
1011             );
1012             m_rendered_fonts[key] = font;
1013             return m_rendered_fonts[key];
1014         } else { // otherwise, the font we found works, so just return it
1015             return it->second;
1016         }
1017     }
1018 }
1019 
1020 #endif
1021