1 /*!
2 * \file
3 * \ingroup text_font
4 * \brief Classes and functions for rendering text in different fonts
5 */
6
7 #ifndef NEW_FONT_H
8 #define NEW_FONT_H
9
10 #define DEFAULT_FIXED_FONT_WIDTH 11
11 #define DEFAULT_FIXED_FONT_HEIGHT 18
12 #define SMALL_FIXED_FONT_WIDTH 8
13 #define SMALL_FIXED_FONT_HEIGHT 15
14 // This value of DEFAULT_SMALL_RATIO is a compromise between 8/11 = 0.7272 and 16/19=0.8421,
15 // which are the ratios of the widths and heights respectively between small and normal characters
16 // in the fixed font in earlier font handling.
17 #define DEFAULT_SMALL_RATIO 0.785f
18
19 #define INGAME_FONT_X_LEN 0.17f
20 #define SMALL_INGAME_FONT_X_LEN 0.12f
21 #define SMALL_INGAME_FONT_Y_LEN 0.17f
22 #define ALT_INGAME_FONT_X_LEN 0.10f
23 #define ALT_INGAME_FONT_Y_LEN 0.15f
24
25 /*!
26 * \ingroup text_font
27 * \brief Enumeration for font categories
28 *
29 * This enumeration defines the different categories of fonts used in the
30 * game. The actual enum values correspond to indices in the font_idxs array,
31 * which holds the actual font numbers.
32 */
33 typedef enum
34 {
35 //! Index for the font used for drawing text in the user interface
36 UI_FONT,
37 //! Index for the font used for drawing text messages
38 CHAT_FONT,
39 //! Index for the font used for drawing names above the characters
40 NAME_FONT,
41 //! Index for the font used for drawing text in books
42 BOOK_FONT,
43 //! INdex for the font used to draw user notes
44 NOTE_FONT,
45 //! Index for the font used to draw the rules
46 RULES_FONT,
47 //! Index for the font used to draw the encyclopedia and help texts
48 ENCYCLOPEDIA_FONT,
49 //! Index used for the font used to draw map marks
50 MAPMARK_FONT,
51 //! Index used for the font used to draw the options window contents
52 CONFIG_FONT,
53 //! Number of font categories
54 NR_FONT_CATS
55 } font_cat;
56
57 //! Enumeration for horizontal text alignment
58 typedef enum
59 {
60 //! Align text left to the given position
61 LEFT,
62 //! Center text around the given position
63 CENTER,
64 //! Align text right to the given position
65 RIGHT
66 } hor_alignment;
67
68 //! Enumeration for vertical text alignment
69 typedef enum
70 {
71 //! Align top of the line to the given position
72 TOP_LINE,
73 //! Align top of the font to the given position
74 TOP_FONT,
75 //! Align bottom of the line to the given position
76 BOTTOM_LINE,
77 //! Center text around the given position, works with multiple lines
78 CENTER_LINE,
79 //! Center first line around given position, assuming it consists of digits
80 CENTER_DIGITS,
81 //! Center first line around given position, assuming it consists of password asterisks
82 CENTER_PASSWORD
83 } ver_alignment;
84
85 #include "client_serv.h"
86 #include "gl_init.h"
87 #include "text.h"
88 #include "widgets.h"
89
90 #ifdef __cplusplus
91
92 #include <array>
93 #include <stdexcept>
94 #include <string>
95 #include <unordered_map>
96 #include <vector>
97 #include <SDL_types.h>
98 #ifdef TTF
99 #include <SDL_ttf.h>
100 #endif // TTF
101 #include "platform.h"
102
103 namespace eternal_lands
104 {
105
106 /*!
107 * \ingroup text_font
108 * \brief Type alias for a byte string, as used in many places in EL
109 */
110 typedef std::basic_string<unsigned char> ustring;
111
112 /*!
113 * \ingroup text_font
114 * \brief Class for font options.
115 *
116 * Class FontOption holds the information necessary to display a font option to the user: the font
117 * name, its file name, the type of font and whether it is a fixed width font.
118 */
119 class FontOption
120 {
121 public:
122 /*!
123 * \brief Constructor
124 *
125 * Create a new font option for the EL bundled font with index \a font_nr. Currently there are
126 * 7 such fonts available:
127 * - 0: textures/font.dds (fixed width)
128 * - 1: textures/font.dds (variable width)
129 * - 2: textures/font2.dds
130 * - 3: textures/font3.dds
131 * - 4: textures/font5.dds
132 * - 5: textures/font6.dds
133 * - 6: textures/font7.dds
134 *
135 * \param font_nr The number of the bundled font.
136 */
137 FontOption(size_t font_nr);
138 #ifdef TTF
139 /*!
140 * \brief Constructor
141 *
142 * Create a new font option for the TrueType font in file \a file_name.
143 *
144 * \param file_name The name of the file of the TrueType font.
145 */
146 FontOption(const std::string& file_name);
147 #endif
148
149 //! Return the font number of a bundled font
font_number()150 size_t font_number() const { return _font_nr; }
151 //! Return the file name of the font
file_name()152 const std::string& file_name() const { return _file_name; }
153 //! Return the base file name of the font, without a path prefix
file_base_name()154 const std::string& file_base_name() const { return _file_base_name; }
155 //! Return the display name of the font
font_name()156 const std::string& font_name() const { return _font_name; }
157 #ifdef TTF
158 //! Return whether the font is a TrueType font
is_ttf()159 bool is_ttf() const { return _is_ttf; }
160 #endif
161 //! Return whether the font is fixed width
is_fixed_width()162 bool is_fixed_width() const { return _fixed_width; }
163 //! Return \c true if the font file cannot be found, or the font is otherwise invalid
failed()164 bool failed() const { return _failed; }
165
166 /*!
167 * \brief Add this font to the multi-selects
168 *
169 * Add this font option to the various font selections in the settings window. If the optional
170 * parameter \a add_button is \c true, a button for the font is immediately added to the
171 * corresponding widget.
172 */
173 void add_select_options(bool add_button=false) const;
174
175 private:
176 // Font number, only for bundled fonts
177 size_t _font_nr;
178 //! File name of the font file or texture image
179 std::string _file_name;
180 //! Base file name of the font file or texture image, without any preceding path
181 std::string _file_base_name;
182 //! Return the display name of the font
183 std::string _font_name;
184 #ifdef TTF
185 //! \c true if this a a True Type font
186 bool _is_ttf;
187 #endif
188 //! \c true if this ais a monospaced font
189 bool _fixed_width;
190 //! \c true if the font file does not exist, or the font is otherwise invalid
191 bool _failed;
192 };
193
194 /*!
195 * \ingroup text_font
196 * \brief Class for text drawing options.
197 *
198 * Class TextDrawOptions can hold options that specify how a text will be
199 * displayed on the screen. Things that can be specified through TextDrawOptions
200 * include:
201 * * The size and color of the text to display
202 * * The maximum width the text can occupy, and the maximum number of lines to draw,
203 * * Alignment of the text: left, right, or centered around the given x position
204 * * Whether or not to draw a semi-transparent background behind the text
205 * * Whether to use ellipsis to indicate too wide text
206 */
207 class TextDrawOptions
208 {
209 public:
210 //! Default foreground color for text
211 static const std::array<float, 3> default_foreground_color;
212 //! Default background color for text
213 static const std::array<float, 3> default_background_color;
214 //! Default color for selected text
215 static const std::array<float, 3> default_selection_color;
216
217 typedef ::hor_alignment Alignment;
218 typedef ::ver_alignment VerticalAlignment;
219
220 //! Bit flags controlling the look of the text
221 enum Flags
222 {
223 //! If set, draw a shadow around the text
224 SHADOW = 1 << 0,
225 //! If set, ignore color characters in the text
226 IGNORE_COLOR = 1 << 1,
227 //! If set, draw a semi-transparent background behind the text
228 HELP = 1 << 2,
229 //! If set, draw ellipsis (...) after truncated strings
230 ELLIPSIS = 1 << 3,
231 //! If set, scale text down if it is too wide
232 SHRINK_TO_FIT = 1 << 4
233 };
234
235 /*!
236 * \brief Constructor
237 *
238 * Create a new TextDrawOptions object, with default settings.
239 */
240 TextDrawOptions();
241
242 //! Return the maximum width the text can occupy
max_width()243 int max_width() const { return _max_width; }
244 //! Return the maximum number of text lines to draw
max_lines()245 int max_lines() const { return _max_lines; }
246 //! Return the scale factor for the text
zoom()247 float zoom() const { return _zoom; }
248 //! Return the scale factor for the spacing between two lines
line_spacing()249 float line_spacing() const { return _line_spacing; }
250 //! Return the horizontal alignment of the text
alignment()251 Alignment alignment() const { return _alignment; }
252 //! Return the vertical alignment of the text
vertical_alignment()253 VerticalAlignment vertical_alignment() const { return _vertical_alignment; }
254 //! Return whether the text is drawn with a shadow background
shadow()255 bool shadow() const { return _flags & SHADOW; }
256 //! Return whether color characters in the text are ignored
ignore_color()257 bool ignore_color() const { return _flags & IGNORE_COLOR; }
258 //! Return whether this is a help text, with semi-transparent background
is_help()259 bool is_help() const { return _flags & HELP; }
260 //! Return whether to truncate wide text with ellipsis (...)
ellipsis()261 bool ellipsis() const { return _flags & ELLIPSIS; }
262 //! Return whether to shrink the text if it does not fit
shrink_to_fit()263 bool shrink_to_fit() const { return _flags & SHRINK_TO_FIT; }
264
265 //! Return whether a valid foreground color was set for this text
has_foreground_color()266 bool has_foreground_color() const { return _fg_color[0] >= 0.0; }
267 //! Return whether a valid background color was set for this text
has_background_color()268 bool has_background_color() const { return _bg_color[0] >= 0.0; }
269
270 //! Set the maximum width (in pixels) the text can occupy to \a width
set_max_width(int width)271 TextDrawOptions& set_max_width(int width)
272 {
273 _max_width = width;
274 return *this;
275 }
276
277 //! Set the maximum number of lines to draw to \a lines
set_max_lines(int lines)278 TextDrawOptions& set_max_lines(int lines)
279 {
280 _max_lines = lines;
281 return *this;
282 }
283
284 //! Set the scale factor for the text to \a zoom
set_zoom(float zoom)285 TextDrawOptions& set_zoom(float zoom)
286 {
287 _zoom = zoom;
288 return *this;
289 }
290
291 //! Multiply the current scale factor by \a scale
scale_zoom(float scale)292 TextDrawOptions& scale_zoom(float scale)
293 {
294 _zoom *= scale;
295 return *this;
296 }
297
298 //! Set the scale factor for the line spacing to \a scale
set_line_spacing(float scale)299 TextDrawOptions& set_line_spacing(float scale)
300 {
301 _line_spacing = scale;
302 return *this;
303 }
304
305 //! Set the horizontal text alignment to \a alignment
set_alignment(Alignment alignment)306 TextDrawOptions& set_alignment(Alignment alignment)
307 {
308 _alignment = alignment;
309 return *this;
310 }
311
312 //! Set the vertical text alignment to \a alignment
set_vertical_alignment(VerticalAlignment alignment)313 TextDrawOptions& set_vertical_alignment(VerticalAlignment alignment)
314 {
315 _vertical_alignment = alignment;
316 return *this;
317 }
318
319 /*!
320 * \brief Set whether to draw a shadow in the background color around the text
321 * \sa set_background
322 */
323 TextDrawOptions& set_shadow(bool shadow=true)
324 {
325 if (shadow)
326 _flags |= SHADOW;
327 else
328 _flags &= ~SHADOW;
329 return *this;
330 }
331
332 /*!
333 * \brief Set the foreground color of the text to (\a r, \a g, \a b).
334 *
335 * If not set, text is drawn in white, unless ignore_color is set, in which
336 * case the current OpenGL color is used.
337 * \sa set_ignore_color
338 */
set_foreground(float r,float g,float b)339 TextDrawOptions& set_foreground(float r, float g, float b)
340 {
341 _fg_color[0] = r;
342 _fg_color[1] = g;
343 _fg_color[2] = b;
344 return *this;
345 }
346
347 /*!
348 * \brief Set the background (shadow) color of the text to (\a r, \a g, \a b).
349 *
350 * If not set, shadows are drawn in black.
351 *
352 * \sa set_shadow
353 */
set_background(float r,float g,float b)354 TextDrawOptions& set_background(float r, float g, float b)
355 {
356 _bg_color[0] = r;
357 _bg_color[1] = g;
358 _bg_color[2] = b;
359 return *this;
360 }
361
362 //! Set whether to ignore color characters in the text
363 TextDrawOptions& set_ignore_color(bool ignore=true)
364 {
365 if (ignore)
366 _flags |= IGNORE_COLOR;
367 else
368 _flags &= ~IGNORE_COLOR;
369 return *this;
370 }
371
372 /*!
373 * \brief Set whether this is a help text.
374 *
375 * Help texts are drawn with a semi-transparent background behind the text,
376 * as if they are on a window.
377 */
378 TextDrawOptions& set_help(bool is_help=true)
379 {
380 if (is_help)
381 _flags |= HELP;
382 else
383 _flags &= ~HELP;
384 return *this;
385 }
386
387 //! Set whether to ellipsis (...) should be added to clipped text
388 TextDrawOptions& set_ellipsis(bool ellipsis=true)
389 {
390 if (ellipsis)
391 _flags |= ELLIPSIS;
392 else
393 _flags &= ~ELLIPSIS;
394 return *this;
395 }
396
397 //! Set the color for selected text to (\a r, \a g, \a b).
set_selection(float r,float g,float b)398 TextDrawOptions& set_selection(float r, float g, float b)
399 {
400 _sel_color[0] = r;
401 _sel_color[1] = g;
402 _sel_color[2] = b;
403 return *this;
404 }
405
406 //! Set whether to shrink the text if it is too wide
407 TextDrawOptions& set_shrink_to_fit(bool shrink=true)
408 {
409 if (shrink)
410 _flags |= SHRINK_TO_FIT;
411 else
412 _flags &= ~SHRINK_TO_FIT;
413 return *this;
414 }
415
416 //! Set the current draw color to the foreground color in these options
417 void use_foreground_color() const;
418 //! Set the current draw color to the background color in these options
419 void use_background_color() const;
420 //! Set the current draw color to the selection color in these options
421 void use_selection_color() const;
422
423 private:
424 //! The maximum width of the text
425 int _max_width;
426 //! The maximum number of lines to draw
427 int _max_lines;
428 //! The scale factor for the text size
429 float _zoom;
430 //! The scale factor for the spacing between lines
431 float _line_spacing;
432 //! The horizontal alignment of the text
433 Alignment _alignment;
434 //! The vertical alignment of the text
435 VerticalAlignment _vertical_alignment;
436 //! Bit flags for further options
437 Uint32 _flags;
438 //! The foreground color of the text
439 std::array<float, 3> _fg_color;
440 //! The shadow color of the text, if shadows are drawn
441 std::array<float, 3> _bg_color;
442 //! The color for selected text
443 std::array<float, 3> _sel_color;
444 };
445
446 /*!
447 * \ingroup text_font
448 * \brief A class for a text font
449 *
450 * Class Font holds information about text fonts, and provides functions to
451 * draw text in a certain font. A font can be either one of the fonts bundled
452 * with the game, or if the TTF compiled option is enabled, a TrueType font
453 * on the user's system.
454 */
455 class Font
456 {
457 public:
458 /*!
459 * Move constructor
460 *
461 * Create a new font as a copy of \a font.
462 * \note This constructor does takes ownership of the font texture; the texture in \a font
463 * is invalidated.
464 *
465 * \param font The font to move into this font
466 */
467 Font(Font&& font);
468 /*!
469 * \brief Create a new font
470 *
471 * Initialize a new internal font. This sets the parameters for the bundled font with the font
472 * number stored in \a option, but does not yet load the font texture because it is called
473 * before OpenGL is initialized.
474 *
475 * \param option The font option for the font to load, holding font number, file and font name
476 */
477 Font(const FontOption& option);
478 #ifdef TTF
479 /*!
480 * \brief Create a new font.
481 *
482 * Create a new font for the TTF font option in \a option, for text with line height \a height
483 * pixels. This only copies the font description, and determines the point size. It does not
484 * yet generate a texture. If \a outline is \c true, a shadow outline will be drawn around the
485 * glyphs, otherwise the glyphs are drawn as they are.
486 *
487 * \param option The font option for the font, holding file and font name
488 * \param height The line height of the opened font
489 * \param outline Whether to draw a shadow outline around the glyphs
490 */
491 Font(const FontOption& option, int height, bool outline);
492 #endif
493 //! Destructor
494 ~Font();
495
496 //! Return the name of the font
font_name()497 const std::string& font_name() const { return _font_name; }
498 //! Return the file name from which the font was loaded
file_name()499 const std::string& file_name() const { return _file_name; }
500 #ifdef TTF
501 //! Check if this font is a TTF font
is_ttf()502 bool is_ttf() const { return _flags & Flags::IS_TTF; }
503 #endif
504 //! Check if the font is fixed width
is_fixed_width()505 bool is_fixed_width() const { return _flags & Flags::FIXED_WIDTH; }
506 //! Check if a texture has been generated for this font
has_texture()507 bool has_texture() const { return _flags & Flags::HAS_TEXTURE; }
508 //! Check if this font is drawn with an outline or not
has_outline()509 bool has_outline() const { return _flags & Flags::HAS_OUTLINE; }
510 //! Check if this font failed to load
failed()511 bool failed() const { return _flags & Flags::FAILED; }
512
513 /*!
514 * \brief Check if a character has a glyph.
515 *
516 * Check if a glyph is defined for a character \a c, i.e. if it can be printed.
517 *
518 * \param c The character to check
519 * \return \c true if the character has a glyph, \c false otherwise.
520 */
has_glyph(unsigned char c)521 static bool has_glyph(unsigned char c)
522 {
523 return get_position(c) >= 0;
524 }
525
526 /*!
527 * \brief Get the width of a character
528 *
529 * Get the drawing width of character \a c when drawn in this font at zoom level \a zoom.
530 *
531 * \param c The character of which to determine the width
532 * \param zoom The zoom factor for drawing the glyph
533 * \return The width of \a c, in pixels.
534 */
535 int width(unsigned char c, float zoom=1.0) const
536 {
537 return width_pos(get_position(c), zoom);
538 }
539 /*!
540 * \brief Get the pen advancement of a character, plus spacing
541 *
542 * Get how far the pen is advanced after drawing character \a c in this font at zoom level
543 * \a zoom. The spacing between two characters is added to the advancement.
544 *
545 * \param c The character of which to determine the width
546 * \param zoom The zoom factor for drawing the glyph
547 * \return The width of \a c and spacing, in pixels.
548 */
549 int advance_spacing(unsigned char c, float zoom=1.0) const
550 {
551 return advance_spacing_pos(get_position(c), zoom);
552 }
553 /*!
554 * \brief Get the maximum character width, plus spacing
555 *
556 * Get the maximum width of a single character in this font when drawn at zoom
557 * level \a zoom, and include the spacing between characters.
558 *
559 * \param zoom The zoom factor for drawing the character.
560 * \return The maximum width of a character including spacing, in pixels.
561 */
562 int max_width_spacing(float zoom=1.0) const;
563 /*!
564 * \brief Get the average character width, plus spacing
565 *
566 * Get an approximation to the average width of a character in this font when
567 * drawn at zoom level \a zoom, including the space between characters,
568 * for some definition of "average". The average is calculated by assigning
569 * a weight to each possible character, and taking the weighted average
570 * of all character widths. The weights are based on a study on normal
571 * English text, so use this function with the following caveats:
572 * 1. Relative frequencies are based on English text, and so may not be
573 * applicable to text in to other languages,
574 * 2. Furthermore, weights are based on text from the New York Times, and so
575 * may not be representative even for English text in EL,
576 * 3. Only ASCII characters were counted in the study (so accented characters
577 * don't contribute), and a few ASCII characters are missing as well
578 * (\c '[', \c '\\', \c ']', \c '^', \c '_', and \c '`' to be exact),
579 * 4. The occurance of the space character was guesstimated from the reported
580 * total number of words in the corpus.
581 *
582 * Proceed to use with caution, do not use this function when you need to be
583 * sure a string will fit within a certain space, use max_width_spacing()
584 * or a monospaced font instead.
585 *
586 * \param zoom The zoom factor for drawing the character.
587 * \return The maximum width of a character including spacing, in pixels.
588 */
589 int average_width_spacing(float zoom=1.0) const;
590 /*!
591 * \brief Get the maximum width of a digit, plus spacing
592 *
593 * Get the maximum width of a single digit character (0-9) in this font when
594 * drawn at zoom level \a zoom, and include the spacing between characters.
595 *
596 * \param zoom The zoom factor for drawing the character.
597 * \return The maximum width of a digit character including spacing, in pixels.
598 */
599 int max_digit_width_spacing(float zoom=1.0) const;
600 /*!
601 * \brief The maximum width of a single name character
602 *
603 * Return the maximum pen advancement for a single name character ('0'-'9', 'a'-'z', 'A'-'Z', or '_')
604 * when drawn in this font at zoom level \a text_zoom, and include the spacing between characters.
605 *
606 * \param zoom The scale factor for the text
607 * \return The maximum name character width incuding spacing, in pixels.
608 */
609 int max_name_width_spacing(float zoom=1.0) const;
610 /*!
611 * \brief Calculate the width of a string
612 *
613 * Calculate the width in pixels of the string \a text of length \a len
614 * when drawn in this font with scale factor zoom.
615 * \note This function assumes the string is a single line. Newline
616 * characters are ignored, and having them in the middle of string will
617 * result in a too large value for the width.
618 *
619 * \param text The string for which to calculate the length
620 * \param len The number of bytes in \a text
621 * \param zoom The scale factor for the text
622 * \return The width of the text in pixels
623 */
624 int line_width(const unsigned char* text, size_t len, float zoom) const;
625 /*!
626 * \brief Calculate the width of a string with final spacing
627 *
628 * Calculate the width in pixels of the string \a text of length \a len,
629 * including the spacing after the final character, when drawn in this font
630 * with scale factor \a zoom.
631 * \note This function assumes the string is a single line. Newline
632 * characters are ignored, and having them in the middle of string will
633 * result in a too large value for the width.
634 *
635 * \param text The string for which to calculate the length
636 * \param len The number of bytes in \a text
637 * \param zoom The scale factor for the text
638 * \return The width of the text in pixels
639 */
640 int line_width_spacing(const unsigned char* text, size_t len, float zoom) const;
641 /*!
642 * \brief Calculate the width of a string with final spacing
643 *
644 * Calculate the width in pixels of the string \a text including the spacing
645 * after the final character, when drawn in this font with scale factor \a zoom.
646 * \note This function assumes the string is a single line. Newline
647 * characters are ignored, and having them in the middle of string will
648 * result in a too large value for the width.
649 *
650 * \param text The string for which to calculate the length
651 * \param zoom The scale factor for the text
652 * \return The width of the text in pixels
653 */
line_width_spacing(const ustring & text,float zoom)654 int line_width_spacing(const ustring& text, float zoom) const
655 {
656 return line_width_spacing(text.data(), text.length(), zoom);
657 }
658 /*!
659 * \brief Get the height of a line.
660 *
661 * Get the height of a single line of text when drawing text at zoom level \a zoom.
662 * \note It is not necessarily the case that two consecutive lines of text consume twice
663 * the line height, the use of the bundled fonts (where the line height is greater than the
664 * spacing) or a custom line spacing may prevent that. Use dimensions() or vertical_advance()
665 * if you need to know the height of a text consiting of multiple lines.
666 *
667 * \param zoom The zoom factor for drawing the text
668 */
669 int height(float zoom=1.0) const;
670 /*!
671 * \brief Get the vertical advancement after a line.
672 *
673 * Get the number of pixels the pen is advanced in the vertical direction after drawing a
674 * line of text at zoom level \a zoom, with line spacing scale factor \a line_spacing.
675 *
676 * \param zoom The zoom factor for drawing the text
677 * \param line_spacing The additional scale factor for the spacing between lines
678 */
679 int vertical_advance(float zoom=1.0, float line_spacing=1.0) const;
680 /*!
681 * \brief Calculate the number of lines that fit.
682 *
683 * Return the maximum number of lines that fit in a window of \a max_height pixels high, when
684 * drawing text in this font at zoom level \a zoom, and line spacing scale factor
685 * \a line_spacing.
686 *
687 * \param max_height The maximum height of the text, in pixels
688 * \param zoom The zoom factor for drawing the text
689 * \param line_spacing The additional scale factor for the spacing between lines
690 */
691 int max_nr_lines(int max_height, float zoom, float line_spacing=1.0) const;
692 /*!
693 * \brief Compute the height of a block of text
694 *
695 * Compute the height of a block of text of \a nr_lines lines, when drawn in this font
696 * at zoom level \a zoom, with line spacing scale factor \a line_spacing.
697 *
698 * \param nr_lines The number of lines in the text
699 * \param text_zoom The zoom factor for drawing the text
700 * \param line_spacing The additional scale factor for the spacing between lines
701 * \return The height of the text in pixels
702 */
703 int text_height(int nr_lines, float zoom, float line_spacing=1.0);
704 /*!
705 * \brief Calculate the dimensions of a block of text
706 *
707 * Calculate the width and height of string \a text of length \a len bytes when drawn in this
708 * font with scale factor \a zoom and with line spacing scale factor \a line_spacing. The
709 * string may contain multiple lines, the width returned is then the width of the widest line.
710 *
711 * \param text The string for which to compute the dimensions
712 * \param len The number of bytes in \a text
713 * \param zoom The scale factor for the text
714 * \param line_spacing The additional scale factor for the spacing between lines
715 * \return The width and height of the text
716 */
717 std::pair<int, int> dimensions(const unsigned char* text, size_t len, float zoom,
718 float line_spacing=1.0) const;
719
720 /*!
721 * \brief Calculate vertical offset of center
722 *
723 * Calculate the offset of the center of the characters in \a text with respect to the center
724 * of the line, when drawn at zoom level \a zoom.
725 *
726 * \param text The string for which to compute center offset
727 * \param len The number of bytes in \a text
728 * \param zoom The scale factor for the text
729 * \return The number of pixels between the center of the line and the center of \a text.
730 */
731 int center_offset(const unsigned char* text, size_t len, float zoom);
732 /*!
733 * \brief Get vertical coordinates
734 *
735 * Get the minimum and maximum offsets of the characters in \a text with respect to the top of
736 * the text line, when drawing the text at zoom level \a zoom.
737 *
738 * \param text The text to get the vertical offsets for
739 * \param len The number of characters in \a text
740 * \param zoom The scale factor for the text
741 * \return The offsets of the top and bottom of the text
742 */
743 std::pair<int, int> top_bottom(const unsigned char* text, size_t len, float zoom);
744
745 /*!
746 * \brief Recompute where the line breaks in a string should occur
747 *
748 * Recomputes the positions in string \a text where line breaks should be placed so that the
749 * string fits into a window. This creates a new string from the the contents of \a text and
750 * inserts \c '\\r' characters at the positions where the line should be broken. The parameter
751 * \a options specifies how the text will be drawn, currently only the \c zoom and \c max_width
752 * fields are used in this function. The optional parameter \a cursor contains the offset of
753 * the cursor position in the text; if it is non-negative the difference in cursor position
754 * will be returned through the third value in the result tuple. The optional parameter
755 * \a max_line_width can be used to retrieve the largest width in pixels of the lines in \a text
756 * after rewrapping.
757 *
758 * \param text the string
759 * \param text_len the actual length of the string
760 * \param options the options defining the layout of the text
761 * \param cursor the cursor position, or a negative number if not used
762 * \param max_line_width pointer the maximum line length after wrapping, or NULL if not used
763 *
764 * \return The wrapped text, the new number of lines in the text, and the difference in
765 * cursor position
766 */
767 std::tuple<ustring, int, int> reset_soft_breaks(const unsigned char *text, size_t text_len,
768 const TextDrawOptions& options, ssize_t cursor = -1, int *max_line_width = nullptr);
769 /*!
770 * \brief Recompute where the line breaks in a string should occur
771 *
772 * Recomputes the positions in string \a text where line breaks should be
773 * placed so that the string fits into a window. This creates a new string
774 * from the the contents of \a text and inserts \c '\\r' characters at the
775 * positions where the line should be broken. The parameter \a options
776 * specifies how the text will be drawn, currently only the \c zoom and
777 * \c max_width field are used int this function.
778 *
779 * \param text the string
780 * \param options the options defining the layout of the text
781 *
782 * \return The wrapped text and the new number of lines in the text.
783 */
reset_soft_breaks(const ustring & text,const TextDrawOptions & options)784 std::pair<ustring, int> reset_soft_breaks(const ustring& text, const TextDrawOptions& options)
785 {
786 auto res = reset_soft_breaks(text.data(), text.length(), options, -1, nullptr);
787 return std::make_pair(std::get<0>(res), std::get<1>(res));
788 }
789
790 /*!
791 * \brief Draw a text string
792 *
793 * Draw the text in the first \a len bytes of \a text, starting at position
794 * \a x, \a y, using the drawing option in \a options.
795 *
796 * \param text The text to draw
797 * \param len The number of bytes in \a text
798 * \param x The left coordinate of the drawn text
799 * \param y The top coordinate of the drawn text
800 * \param options Options defining the layout of the text
801 * \param sel_begin Start index of selected text
802 * \param sel_end End index of selected text (one past last selected character)
803 */
804 void draw(const unsigned char* text, size_t len, int x, int y,
805 const TextDrawOptions &options, size_t sel_begin=0, size_t sel_end=0) const;
806 /*!
807 * \brief Draws messages in a buffer to the screen
808 *
809 * Draws the messages in buffer \a msgs to the screen, starting with character
810 * \a offset_start in message number \a msg_start.
811 *
812 * \param msgs the message buffer
813 * \param msgs_size the total number of messages that \a msgs can hold
814 * \param x x coordinate of the position to start drawing
815 * \param y y coordinate of the position to start drawing
816 * \param filter draw only messages in channel \a filter. Choose
817 * FILTER_ALL for displaying all messages
818 * \param msg_start index of the first message to display
819 * \param offset_start the first character in message \a msg_start to display
820 * \param options Options defining the layout of the text
821 * \param cursor if >= 0, the position at which to draw the cursor
822 * \param[in,out] select information about current selection. draw_messages()
823 * fills the select->lines array.
824 *
825 * \callgraph
826 */
827 void draw_messages(const text_message *msgs, size_t msgs_size, int x, int y,
828 Uint8 filter, size_t msg_start, size_t offset_start,
829 const TextDrawOptions &options, ssize_t cursor, select_info* select) const;
830 /*!
831 * \brief Draw the console separator
832 *
833 * When there are more messages than can fit on a single screen, the user can
834 * scroll up to see the previous messages. When they do, a separator is
835 * drawn by this function to indicate that more messages follow.
836 *
837 * \param x_space Horizontal space tokeep free on either side
838 * \param y Vertical position at which the line should be drawn
839 * \param options Text options for drawing the separator
840 */
841 void draw_console_separator(int x_space, int y, const TextDrawOptions& options) const;
842 #ifdef ELC
843 #ifndef MAP_EDITOR2
844 void draw_ortho_ingame_string(const unsigned char* text, size_t len,
845 float x, float y, float z, int max_lines, float zoom_x, float zoom_y) const;
846 #endif // ! MAP_EDITOR2
847 #endif // ELC
848
849 private:
850 //! Structure for glyph metrics
851 struct Metrics
852 {
853 //! Actual width of the character in the font texture, in pixels
854 int width;
855 //! How far to advance the pen after drawing this glyph
856 int advance;
857 //! Horizontal offset for drawing the character
858 int x_off;
859 //! Offset from top of line to top of glyph
860 int top;
861 //! Offset from top of line to bottom of glyph
862 int bottom;
863 //! Left side of glyph in the texture
864 float u_start;
865 //! Top of glyph in the texture
866 float v_start;
867 //! Right side of glyph in the texture
868 float u_end;
869 //! Bottom of glyph in the texture
870 float v_end;
871
872 //! Default constructor
MetricsMetrics873 Metrics(): width(0), advance(0), x_off(0), top(0), bottom(0), u_start(0.0), v_start(0.0),
874 u_end(0.0), v_end(0.0) {}
875 };
876
877 //! The number of lines in a font texture
878 static const size_t font_nr_lines = 10;
879 //! The number of glyphs on a single line in a font texture
880 static const size_t font_chars_per_line = 14;
881 //! The total number of different glyphs we recognise
882 static const size_t nr_glyphs = 9*14 + 6;
883 //! Horizontal space in the texture for a single glyph in a bundled font
884 static const int font_block_width = 18;
885 //! Vertical space in the texture for a single glyph in a bundled font
886 static const int font_block_height = 21;
887 //! Normal line height for unscaled text in a bundled font
888 static const int default_vertical_advance = 18;
889 #ifdef TTF
890 //! Point size with which TrueType fonts are opened
891 static const int ttf_point_size = 40;
892 #endif
893 //! Relative frequencies for characters in normal English text
894 static const std::array<int, nr_glyphs> letter_freqs;
895 //! Ellipsis string for clipped text
896 static const ustring ellipsis;
897
898 //! Flags indicating the status and properties of a font
899 enum Flags
900 {
901 #ifdef TTF
902 //! Set if the font is a TTF Font
903 IS_TTF = 1 << 0,
904 #endif
905 //! Set if the font is fixed width, i.e. all characters have the same width
906 FIXED_WIDTH = 1 << 1,
907 //! Set if the texture for the font is loaded or generated
908 HAS_TEXTURE = 1 << 2,
909 //! Set if this font has a shadow outline around the glyphs
910 HAS_OUTLINE = 1 << 3,
911 //! Set if loading the font failed, and a fallback should be used
912 FAILED = 1 << 4
913 };
914
915 //! Name of this font. This will be shown on the multi-select button.
916 std::string _font_name;
917 //! Name of the files containing the font texture or TTF font description.
918 std::string _file_name;
919 //! Flags indicating the type and status of this font.
920 Uint32 _flags;
921 //! Width of the font texture in pixels.
922 int _texture_width;
923 //! Height of the font texture in pixels.
924 int _texture_height;
925 //! Glyph metrics for each supported character
926 std::array<Metrics, nr_glyphs> _metrics;
927 //! Width reserved for a character in the texture
928 int _block_width;
929 //! Height of a single character in pixels
930 int _line_height;
931 //! How far to advance the pen vertically when moving to the next line
932 int _vertical_advance;
933 //! Distance from top of line to top of font
934 int _font_top_offset;
935 //! Distance from top of line to center of digits
936 int _digit_center_offset;
937 //! Distance from top of line to center of the asterisk
938 int _password_center_offset;
939 //! Maximum width of a glyph
940 int _max_advance;
941 //! Maximum width of a digit '0'-'9'
942 int _max_digit_advance;
943 //! Maximum width of a name character '0'-'9', 'A'-'Z', 'a'-'z' or '_'
944 int _max_name_advance;
945 //! "Typical" character width for English text
946 int _avg_advance;
947 //! Distance between characters when drawn (at default zoom level)
948 int _spacing;
949 //! Scale factor in the horizontal direction
950 float _scale_x;
951 //! Scale factor in the vertical direction
952 float _scale_y;
953 #ifdef TTF
954 //! Point size to open the font file with
955 int _point_size;
956 //! Outline size in pixels
957 int _outline;
958 union
959 {
960 //! ID of the texture for this font in the texture cache.
961 Uint32 cache_id;
962 //! Open GL texture ID for a generated texture.
963 GLuint gl_id;
964 } _texture_id;
965 #else
966 //! ID of the texture for this font in the texture cache
967 Uint32 _texture_id;
968 #endif
969
970 friend class FontManager;
971
972 /*!
973 * \brief Get the position of a glyph in the texture
974 *
975 * \param c The byte for which to get the position
976 * \return The position in the font texture, of -1 if \a c is not a valid glyph.
977 */
978 static int get_position(unsigned char c);
979 /*!
980 * \brief Get the width of a character
981 *
982 * Get the width of the glyph at position \a pos in the texture when drawn
983 * in this font at zoom level \a zoom.
984 *
985 * \param pos The position of the glyph in the texture
986 * \param zoom The zoom factor for drawing the glyph
987 */
988 int width_pos(int pos, float zoom=1.0) const;
989 /*!
990 * \brief Get the pen advancement of a character, plus spacing
991 *
992 * Get how far the pen is advanced after drawing the glyph at position \a pos in the texture,
993 * when drawn in this font at zoom level \a zoom. The spacing between two characters is added
994 * to the advancement.
995 *
996 * \param pos The position of the glyph in the texture
997 * \param zoom The zoom factor for drawing the glyph
998 */
999 int advance_spacing_pos(int pos, float zoom=1.0) const;
1000 /*!
1001 * \brief Get vertical coordinates
1002 *
1003 * Get the minimum and maximum offsets of the characters in \a text with respect to the top of
1004 * the text line, before any scaling.
1005 *
1006 * \param text The text to get the vertical offsets for
1007 * \param len The number of characters in \a text
1008 * \return The offsets of the top and bottom of the text
1009 */
1010 std::pair<int, int> top_bottom_unscaled(const unsigned char* text, size_t len);
1011
1012 /*!
1013 * \brief Load or generate the texture for this font.
1014 *
1015 * Load the texture into the texture cache for normal fonts, or generate
1016 * a texture atlas for TTF fonts.
1017 *
1018 * \return \c true on success, \c false on failure.
1019 */
1020 bool load_texture();
1021 //! Bind the font texture for this font
1022 void bind_texture() const;
1023 /*!
1024 * \brief Get texture coordinates for a character
1025 *
1026 * Get the texture coordinates in the font texture for the character at
1027 * position \a pos.
1028 *
1029 * \param pos The position of the character within the texture
1030 * \param u_start On exit, the left coordinate
1031 * \param u_end On exit, the right coordinate
1032 * \param v_start On exit, the top coordinate
1033 * \param v_end On exit, the bottom coordinate
1034 */
1035 void get_texture_coordinates(int pos,
1036 float &u_start, float &u_end, float &v_start, float &v_end) const;
1037
1038 /*!
1039 * \brief Set the current draw color.
1040 *
1041 * Set the drawing color for the text to the color define in colors_list
1042 * at index \a color.
1043 *
1044 * \param color The index of the text color in the \see colors_list.
1045 */
1046 static void set_color(int color);
1047
1048 /*!
1049 * \brief Draw a single character
1050 *
1051 * Draw a single character \a c at position \a x, \a y with its sized scaled
1052 * by a factor \a zoom. This function only adds the quad with the correct
1053 * coordinates and texture coordinates; calls to this functions should be
1054 * done inside a glBegin(GL_QUADS)/glEnd() pair. If \a c is a color character,
1055 * the color is set and nothing is drawn.
1056 *
1057 * \param c The character to draw
1058 * \param x The x coordinate of the left side of the drawn character
1059 * \param y The x coordinate of the top of the drawn character
1060 * \param zoom The scale factor for the character
1061 * \param ignore_color If \c true, color characters are ignored and the
1062 * drawing color is left unchanged.
1063 *
1064 * \return The width of the drawn character, or 0 for color characters or
1065 * invalid characters
1066 */
1067 int draw_char(unsigned char c, int x, int y, float zoom, bool ignore_color) const;
1068 /*!
1069 * \brief Draw background for help texts
1070 *
1071 * Draw a semi-transparent background box for tooltips.
1072 *
1073 * \param x The x coordinate of the left side of the box
1074 * \param y The y coordinate of the top of the box
1075 * \param width The width of the box in pixels
1076 * \param height The height of the box in pixels
1077 */
1078 void draw_help_background(int x, int y, int width, int height) const;
1079 /*!
1080 * \brief Draw a single line of text
1081 *
1082 * Draw a single line of text in \a text of length \a len bytes, starting
1083 * at position \a x, \a y and drawing to the left.
1084 * \note This function is for drawing a single line. Any newlines in \a text
1085 * are ignored.
1086 * \note The alignment option in \a options has no effect for this function,
1087 * text is always drawn left to right.
1088 *
1089 * \param text The line of text to draw
1090 * \param len The number of bytes in text to draw
1091 * \param x The x coordinate of the left of the line
1092 * \param y The y coordinate of the top of the line
1093 * \param options Drawing options for the text
1094 * \param sel_begin Start index of selected text
1095 * \param sel_end End index of selected text (one past last selected character)
1096 *
1097 */
1098 void draw_line(const unsigned char* text, size_t len, int x, int y,
1099 const TextDrawOptions &options, size_t sel_begin=0, size_t sel_end=0) const;
1100 /*!
1101 * \brief Clip a line of text
1102 *
1103 * Clip a line of text such that the remainder fits into \a max_width pixels.
1104 * This function takes alignment into account: left aligned text is clipped
1105 * on the right, right-aligned text on the left, centered text on both sides
1106 * equally. In case color characters are clipped, the last color character
1107 * clipped on the left and right are returned through \a before_color and
1108 * \a after_color.
1109 *
1110 * \param text The text to clip
1111 * \param len The number of bytes in \a text
1112 * \param options Drawing options for the text
1113 * \param before_color On exit, the last color character clipped before the
1114 * remaining string, or 0 if there was none.
1115 * \param after_color On exit, the last color character clipped after the
1116 * remaining string, or 0 if there was none.
1117 * \param width On exit, the remaining width of the clipped string.
1118 * \return Start index and length of the clipped substring
1119 */
1120 std::pair<size_t, size_t> clip_line(const unsigned char* text, size_t len,
1121 const TextDrawOptions &options, unsigned char &before_color, unsigned char &after_color,
1122 int &width) const;
1123
1124 #ifdef TTF
1125 /*!
1126 * \brief Render a single glyph
1127 *
1128 * Render the glyph for position \a pos with size \a size in the font atlas \a surface, using
1129 * font \a font. The vertical offset parameter \a y_delta is used to try and center the glyphs
1130 * vertically, making vertical alignment of text easier.
1131 *
1132 * \param pos The position of the glyph to draw
1133 * \param size The size of the rendered glyph
1134 * \param y_delta Vertical offset for placing the glyph in the texture
1135 * \param font The font with which to render the glyph
1136 * \param outline_size If positive, the width of a semi-transparent outline around the glyph
1137 * \param surface The surface on which the glyph is rendered
1138 * \return \c true if the glyph was successfully rendered, \c false otherwise.
1139 */
1140 bool render_glyph(size_t i_glyph, int size, int y_delta, int outline_size, TTF_Font *font,
1141 SDL_Surface *surface);
1142 /*!
1143 * \brief Find an appropriate font size
1144 *
1145 * Find a point size for this font such that the line height is \a height pixels.
1146 *
1147 * \param height The line height to target
1148 * \return A point size for this font which gives the correct line height, or 0 on failure
1149 */
1150 int find_point_size(int height);
1151 /*!
1152 * \brief Build a texture for a TTF font
1153 *
1154 * Build a texture containing all supported glyphs from the TrueType font associated with
1155 * this font.
1156 *
1157 * \return \c true on succes, \c false on failure.
1158 */
1159 bool build_texture_atlas();
1160 #endif // TTF
1161
1162 /*!
1163 * \brief Calculate the average character width.
1164 *
1165 * Calculate a weighted average character width based on the widths of the characters and
1166 * estimated letter frequencies in English text.
1167 *
1168 * \return The average width
1169 */
1170 int calc_average_advance();
1171 };
1172
1173 /*!
1174 * \brief Class for managing fonts
1175 *
1176 * Class FontManager is used as an entry point to font handling. It holds a list
1177 * of all known fonts, as well as a font number and scale factor for a number
1178 * of font categories. The font categories are used for drawing different kinds
1179 * of texts; by changing the font for a certain category all windows and widgets
1180 * using this category are updated automatically. Class FontManager is a singleton
1181 * class: all access to this class must go through get_instance().
1182 * \sa font_cat
1183 */
1184 class FontManager
1185 {
1186 public:
1187 // Use font category enumeration shared with C code.
1188 typedef ::font_cat Category;
1189
1190 //! The font numbers for each font category
1191 static std::array<size_t, NR_FONT_CATS> font_idxs;
1192 //! The zoom factor for each font category
1193 static std::array<float, NR_FONT_CATS> font_scales;
1194
1195 //! Get the singleton FontManager instance
get_instance()1196 static FontManager& get_instance()
1197 {
1198 static FontManager manager;
1199 return manager;
1200 }
1201
1202 //! Check if this font manager has been initialized
is_initialized()1203 bool is_initialized() const { return !_options.empty(); }
1204 /*!
1205 * \brief Initialize the font manager.
1206 *
1207 * This adds the standard fonts bundled with EL to the font manager, and
1208 * if TTF fonts are enabled, scans the TTF path for True Type fonts
1209 * to add as well.
1210 */
1211 bool initialize();
1212
1213 /*!
1214 * \brief Return the font number of a fixed width font
1215 *
1216 * Return the font number for the \a idx'th fixed width font.
1217 *
1218 * \param idx The number of the font in the list of fixed width fonts only
1219 * \return The index of the font in the list of all fonts
1220 */
fixed_width_font_number(size_t idx)1221 size_t fixed_width_font_number(size_t idx) const
1222 {
1223 try
1224 {
1225 return _fixed_width_idxs.at(idx);
1226 }
1227 catch (const std::out_of_range&)
1228 {
1229 // Return standard fixed width font on invalid index
1230 return 0;
1231 }
1232 }
1233
1234 /*!
1235 * \brief Get the pend advancement of a character, plus spacing
1236 *
1237 * Get how far the pen is advanced after drawing character \a c in the font for category \a cat,
1238 * at zoom level \a zoom. The spacing between two characters is added to the advancement.
1239 *
1240 * \param cat The font category for the font used
1241 * \param c The character for which to get the width
1242 * \param text_zoom The scale factor for the text
1243 * \return The width of the character and spacing, in pixels.
1244 */
1245 int advance_spacing(Category cat, unsigned char c, float text_zoom=1.0)
1246 {
1247 return get(cat, text_zoom).advance_spacing(c, text_zoom * font_scales[cat]);
1248 }
1249 /*!
1250 * \brief The maximum width of a single character
1251 *
1252 * Return the maximum a single character can occupy when drawn in the font
1253 * for category \a cat at zoom level \a text_zoom, and include the spacing
1254 * between characters.
1255 *
1256 * \param cat The font category for the font used
1257 * \param text_zoom The scale factor for the text
1258 * \return The maximum character width incuding spacing, in pixels.
1259 */
1260 int max_width_spacing(Category cat, float text_zoom=1.0)
1261 {
1262 return get(cat, text_zoom).max_width_spacing(text_zoom * font_scales[cat]);
1263 }
1264 /*!
1265 * \brief Get the average character width, plus spacing
1266 *
1267 * Get an approximation to the average width of a character in the font for
1268 * category \a cat when drawn at zoom level \a text_zoom, including the space
1269 * between characters, for some definition of "average". See the note
1270 * in Font::average_width_spacing() for some caveats when using this function.
1271 *
1272 * \param cat The font category for the font used
1273 * \param text_zoom The zoom factor for drawing the character.
1274 * \return The maximum width of a character including spacing, in pixels.
1275 */
1276 int average_width_spacing(Category cat, float text_zoom=1.0)
1277 {
1278 return get(cat, text_zoom).average_width_spacing(text_zoom * font_scales[cat]);
1279 }
1280 /*!
1281 * \brief The maximum width of a single digit character
1282 *
1283 * Return the maximum a single digit character (0-9) can occupy when drawn
1284 * in the font for category \a cat at zoom level \a text_zoom, and include
1285 * the spacing between characters.
1286 *
1287 * \param cat The font category for the font used
1288 * \param text_zoom The scale factor for the text
1289 * \return The maximum digit character width incuding spacing, in pixels.
1290 */
1291 int max_digit_width_spacing(Category cat, float text_zoom=1.0)
1292 {
1293 return get(cat, text_zoom).max_digit_width_spacing(text_zoom * font_scales[cat]);
1294 }
1295 /*!
1296 * \brief The maximum width of a single name character
1297 *
1298 * Return the maximum pen advancement for a single name character ('0'-'9', 'a'-'z', 'A'-'Z', or '_')
1299 * when drawn in the font for category \a cat at zoom level \a text_zoom, and include the
1300 * spacing between characters.
1301 *
1302 * \param cat The font category for the font used
1303 * \param text_zoom The scale factor for the text
1304 * \return The maximum name character width incuding spacing, in pixels.
1305 */
1306 int max_name_width_spacing(Category cat, float text_zoom=1.0)
1307 {
1308 return get(cat, text_zoom).max_name_width_spacing(text_zoom * font_scales[cat]);
1309 }
1310 /*!
1311 * \brief Calculate the width of a string
1312 *
1313 * Calculate the width in pixels of the string \a text of length \a len
1314 * when drawn in the font for category \a cat.
1315 * \note This function assumes the string is a single line. Newline
1316 * characters are ignored, and having them in the middle of string will
1317 * result in a too large value for the width.
1318 *
1319 * \param cat The font category for the font used
1320 * \param text The string for which to calculate the length
1321 * \param len The number of bytes in \a text
1322 * \param text_zoom The scale factor for the text
1323 * \return The width of the text in pixels
1324 */
1325 int line_width(Category cat, const unsigned char* text, size_t len,
1326 float text_zoom=1.0)
1327 {
1328 return get(cat, text_zoom).line_width(text, len, text_zoom * font_scales[cat]);
1329 }
1330 /*!
1331 * \brief The height of a text line
1332 *
1333 * Return the height of a line of text when drawn in the font for category
1334 * \a cat with scale factor \a text_zoom.
1335 * \note It is not necessarily the case that two consecutive lines of text consume twice
1336 * the line height, the use of the bundled fonts (where the line height is greater than the
1337 * spacing) or a custom line spacing may prevent that. Use dimensions() or vertical_advance()
1338 * if you need to know the height of a text consiting of multiple lines.
1339 *
1340 * \param cat The font category for the font used
1341 * \param text_zoom The scale factor for the text
1342 * \return The height of the text in pixels
1343 */
1344 int line_height(Category cat, float text_zoom=1.0)
1345 {
1346 return get(cat, text_zoom).height(text_zoom * font_scales[cat]);
1347 }
1348 /*!
1349 * \brief Get the vertical advancement after a line.
1350 *
1351 * Get the number of pixels the pen is advanced in the vertical direction after drawing a
1352 * line of text at zoom level \a text_zoom, with line spacing scale factor \a line_spacing.
1353 *
1354 * \param cat The font category for the font used
1355 * \param text_zoom The zoom factor for drawing the text
1356 * \param line_spacing The additional scale factor for the spacing between lines
1357 * \return The number of pixels the pen is shifted down after a line
1358 */
1359 int vertical_advance(Category cat, float text_zoom=1.0, float line_spacing=1.0)
1360 {
1361 return get(cat, text_zoom).vertical_advance(text_zoom * font_scales[cat], line_spacing);
1362 }
1363 /*!
1364 * \brief Calculate the number of lines that fit.
1365 *
1366 * Return the maximum number of lines that fit in a window of \a max_height pixels high, when
1367 * drawing text in the font for category \a cat at zoom level \a text_zoom, with line spacing
1368 * scale factor \a line_spacing.
1369 *
1370 * \param cat The font category for the font used
1371 * \param max_height The maximum height for the text, in pixels
1372 * \param text_zoom The zoom factor for drawing the text
1373 * \param line_spacing The additional scale factor for the spacing between lines
1374 * \return The maximum number of lines that fit
1375 */
1376 int max_nr_lines(Category cat, int max_height, float text_zoom, float line_spacing=1.0)
1377 {
1378 return get(cat, text_zoom).max_nr_lines(max_height, text_zoom * font_scales[cat], line_spacing);
1379 }
1380 /*!
1381 * \brief Compute the height of a block of text
1382 *
1383 * Compute the height of a block of text of \a nr_lines lines, when drawn in the font for
1384 * category \a cat at zoom level \a zoom, with line spacing scale factor \a line_spacing.
1385 *
1386 * \param cat The font category for the font used
1387 * \param nr_lines The number of lines in the text
1388 * \param text_zoom The zoom factor for drawing the text
1389 * \param line_spacing The additional scale factor for the spacing between lines
1390 * \return The height of the text in pixels
1391 */
1392 int text_height(font_cat cat, int nr_lines, float text_zoom, float line_spacing=1.0)
1393 {
1394 return get(cat, text_zoom).text_height(nr_lines, text_zoom * font_scales[cat], line_spacing);
1395 }
1396 /*!
1397 * \brief Calculate the dimensions of a block of text
1398 *
1399 * Calculate the width and height of string \a text of length \a len bytes when drawn in the
1400 * font for category \a cat, with scale factor \a zoom and line spacing scale factor
1401 * \a line_spacing. The string may contain multiple lines, the width returned is then the
1402 * width of the widest line.
1403 *
1404 * \param cat The font category for the font used
1405 * \param text The string for which to compute the dimensions
1406 * \param len The number of bytes in \a text
1407 * \param text_zoom The scale factor for the text
1408 * \param line_spacing The additional scale factor for the spacing between lines
1409 * \return The width and height of the text
1410 */
1411 std::pair<int, int> dimensions(Category cat, const unsigned char* text, size_t len,
1412 float text_zoom, float line_spacing=1.0)
1413 {
1414 return get(cat, text_zoom).dimensions(text, len, text_zoom * font_scales[cat], line_spacing);
1415 }
1416
1417 /*!
1418 * \brief Calculate vertical offset of center
1419 *
1420 * Calculate the offset of the center of the characters in \a text with respect to the center
1421 * of the line, when drawn in the font for category \a cat at zoom level \a zoom.
1422 *
1423 * \param cat The font category for the font used
1424 * \param text The string for which to compute center offset
1425 * \param len The number of bytes in \a text
1426 * \param text_zoom The scale factor for the text
1427 * \return The number of pixels between the center of the line and the center of \a text.
1428 */
center_offset(Category cat,const unsigned char * text,size_t len,float text_zoom)1429 int center_offset(Category cat, const unsigned char* text, size_t len, float text_zoom)
1430 {
1431 return get(cat, text_zoom).center_offset(text, len, text_zoom * font_scales[cat]);
1432 }
1433 /*!
1434 * \brief Get vertical coordinates
1435 *
1436 * Get the minimum and maximum offsets of the characters in \a text with respect to the top of
1437 * the text line, when drawing the text in the font for category \a cat at zoom level \a zoom.
1438 *
1439 * \param cat The font category for the font used
1440 * \param text The text to get the vertical offsets for
1441 * \param len The number of characters in \a text
1442 * \param text_zoom The scale factor for the text
1443 * \return The offsets of the top and bottom of the text
1444 */
top_bottom(Category cat,const unsigned char * text,size_t len,float text_zoom)1445 std::pair<int, int> top_bottom(Category cat, const unsigned char* text, size_t len, float text_zoom)
1446 {
1447 return get(cat, text_zoom).top_bottom(text, len, text_zoom * font_scales[cat]);
1448 }
1449
1450
1451 /*!
1452 * \brief Recompute where the line breaks in a string should occur
1453 *
1454 * Recomputes the positions in string \a text where line breaks should be placed so that the
1455 * string fits into a window. This creates a new string from the the contents of \a text and
1456 * inserts \c '\\r' characters at the positions where the line should be broken. The parameter
1457 * \a options specifies how the text will be drawn, currently only the \c zoom and \c max_width
1458 * fields are used in this function. The optional parameter \a cursor contains the offset of
1459 * the cursor position in the text; if it is non-negative the difference in cursor position
1460 * will be returned through the third value in the result tuple. The optional parameter
1461 * \a max_line_width can be used to retrieve the largest width in pixels of the lines in \a text
1462 * after rewrapping.
1463 *
1464 * \param cat the font category in which the string is to be drawn
1465 * \param text the string
1466 * \param text_len the actual length of the string
1467 * \param options the options defining the layout of the text
1468 * \param cursor pointer to the cursor position, or NULL if not used
1469 * \param max_line_width pointer the maximum line length after wrapping, or NULL if not used
1470 *
1471 * \return The wrapped text, the new number of lines in the text, and the difference in
1472 * cursor position
1473 */
1474 std::tuple<ustring, int, int> reset_soft_breaks(Category cat, const unsigned char *text,
1475 size_t text_len, const TextDrawOptions& options, int cursor = -1, int *max_line_width = nullptr)
1476 {
1477 TextDrawOptions cat_options = TextDrawOptions(options).scale_zoom(font_scales[cat]);
1478 return get(cat, options.zoom())
1479 .reset_soft_breaks(text, text_len, cat_options, cursor, max_line_width);
1480 }
1481 /*!
1482 * \brief Recompute where the line breaks in a string should occur
1483 *
1484 * Recomputes the positions in string \a text where line breaks should be
1485 * placed so that the string fits into a window. This creates a new string
1486 * from the the contents of \a text and inserts \c '\\r' characters at the
1487 * positions where the line should be broken. The parameter \a options
1488 * specifies how the text will be drawn, currently only the \c zoom and
1489 * \c max_width field are used int this function.
1490 *
1491 * \param cat the font category in which the string is to be drawn
1492 * \param text the string
1493 * \param options the options defining the layout of the text
1494 *
1495 * \return The wrapped text, the new number of lines in the text, and the difference in
1496 * cursor position
1497 */
reset_soft_breaks(Category cat,const ustring & text,const TextDrawOptions & options)1498 std::pair<ustring, int> reset_soft_breaks(Category cat, const ustring& text,
1499 const TextDrawOptions& options)
1500 {
1501 TextDrawOptions cat_options = TextDrawOptions(options).scale_zoom(font_scales[cat]);
1502 return get(cat, options.zoom()).reset_soft_breaks(text, cat_options);
1503 }
1504
1505 /*!
1506 * \brief Draw a text string
1507 *
1508 * Draw the text in the first \a len bytes of \a text, starting at position
1509 * \a x, \a y, using the drawing option in \a options, using the font for
1510 * category \a cat.
1511 *
1512 * \param cat The font category for the text
1513 * \param text The text to draw
1514 * \param len The number of bytes in \a text
1515 * \param x The left coordinate of the drawn text
1516 * \param y The top coordinate of the drawn text
1517 * \param options Options defining the layout of the text
1518 * \param sel_begin Start index of selected text
1519 * \param sel_end End index of selected text (one past last selected character)
1520 */
1521 void draw(Category cat, const unsigned char* text, size_t len, int x, int y,
1522 const TextDrawOptions &options, size_t sel_begin=0, size_t sel_end=0)
1523 {
1524 TextDrawOptions cat_options = TextDrawOptions(options).scale_zoom(font_scales[cat]);
1525 get(cat, options.zoom()).draw(text, len, x, y, cat_options, sel_begin, sel_end);
1526 }
1527 /*!
1528 * \brief Draws messages in a buffer to the screen
1529 *
1530 * Draws the messages in buffer \a msgs to the screen using the font for
1531 * category \a cat, starting with character \a offset_start in message
1532 * number \a msg_start.
1533 *
1534 * \param cat The font category for the text
1535 * \param msgs the message buffer
1536 * \param msgs_size the total number of messages that \a msgs can hold
1537 * \param x x coordinate of the position to start drawing
1538 * \param y y coordinate of the position to start drawing
1539 * \param filter draw only messages in channel \a filter. Choose
1540 * FILTER_ALL for displaying all messages
1541 * \param msg_start index of the first message to display
1542 * \param offset_start the first character in message \a msg_start to display
1543 * \param options Options defining the layout of the text
1544 * \param cursor if >= 0, the position at which to draw the cursor
1545 * \param[in,out] select information about current selection. draw_messages()
1546 * fills the select->lines array.
1547 *
1548 * \callgraph
1549 */
draw_messages(Category cat,const text_message * msgs,size_t msgs_size,int x,int y,Uint8 filter,size_t msg_start,size_t offset_start,const TextDrawOptions & options,ssize_t cursor,select_info * select)1550 void draw_messages(Category cat, const text_message *msgs, size_t msgs_size,
1551 int x, int y, Uint8 filter, size_t msg_start, size_t offset_start,
1552 const TextDrawOptions &options, ssize_t cursor, select_info* select)
1553 {
1554 TextDrawOptions cat_options = TextDrawOptions(options).scale_zoom(font_scales[cat]);
1555 get(cat, options.zoom()).draw_messages(msgs, msgs_size, x, y, filter, msg_start, offset_start,
1556 cat_options, cursor, select);
1557 }
1558 /*!
1559 * \brief Draw the console separator
1560 *
1561 * When there are more messages than can fit on a single screen, the user can
1562 * scroll up to see the previous messages. When they do, a separator is
1563 * drawn by this function to indicate that more messages follow. The font
1564 * category should normally be CHAT_FONT, as it is only used in the console
1565 * window.
1566 *
1567 * \param cat The font category for the separator
1568 * \param x_space Horizontal space to keep free on either side
1569 * \param y Vertical position at which the line should be drawn
1570 * \param options Text options for drawing the separator
1571 */
draw_console_separator(Category cat,int x_space,int y,const TextDrawOptions & options)1572 void draw_console_separator(Category cat, int x_space, int y,
1573 const TextDrawOptions& options)
1574 {
1575 TextDrawOptions cat_options = TextDrawOptions(options).scale_zoom(font_scales[cat]);
1576 get(cat, options.zoom()).draw_console_separator(x_space, y, cat_options);
1577 }
1578 #ifdef ELC
1579 #ifndef MAP_EDITOR2
draw_ortho_ingame_string(Category cat,const unsigned char * text,size_t len,float x,float y,float z,int max_lines,float zoom_x,float zoom_y)1580 void draw_ortho_ingame_string(Category cat, const unsigned char* text, size_t len,
1581 float x, float y, float z, int max_lines, float zoom_x, float zoom_y)
1582 {
1583 get(cat, zoom_y).draw_ortho_ingame_string(text, len, x, y, z, max_lines,
1584 zoom_x * font_scales[cat], zoom_y * font_scales[cat]);
1585 }
1586 #endif // !MAP_EDITOR_2
1587 #endif // ELC
1588
1589 /*!
1590 * \brief Set the config font
1591 *
1592 * Copy the current font index and scale of the UI_FONT category to that
1593 * of the CONFIG_FONT category. This allows us to change the UI font
1594 * without changing the way the options window is drawn, and hopefully
1595 * stops the user from then being unable to change the font back.
1596 */
set_config_font()1597 void set_config_font()
1598 {
1599 font_idxs[CONFIG_FONT] = font_idxs[UI_FONT];
1600 font_scales[CONFIG_FONT] = font_scales[UI_FONT];
1601 }
1602
1603 #ifdef TTF
1604 //! Disable TrueType fonts, allowing bundled fonts only.
1605 void disable_ttf();
1606 //! Enable TrueTyoe fonts, restoring previous font indices if possible
1607 void enable_ttf();
1608 #endif
1609
1610 private:
1611 //! The number of fonts bundled with EL itself
1612 static const size_t _nr_bundled_fonts = 7;
1613 //! The fonts to use by default for each category
1614 static const std::array<size_t, NR_FONT_CATS> _default_font_idxs;
1615
1616 //! The list of known font options
1617 std::vector<FontOption> _options;
1618 //! Map from font number and line height to actual font
1619 std::unordered_map<uint32_t, Font> _fonts;
1620 //! Lookup table mapping indices of fixed width fonts to indices in the _fonts array
1621 std::vector<size_t> _fixed_width_idxs;
1622 #ifdef TTF
1623 /*!
1624 * When disabling TrueType fonts, the current font file names are stored in this
1625 * array. If TTF support is enabled again in the same session, they can be
1626 * restored again without the user having to search the fonts in the options
1627 * window.
1628 */
1629 std::array<std::string, NR_FONT_CATS> _saved_font_files;
1630 #endif
1631
1632 /*!
1633 * \brief Constructor
1634 *
1635 * Create a new font manager, without fonts to manage so far.
1636 */
FontManager()1637 FontManager(): _options(), _fonts(), _fixed_width_idxs()
1638 #ifdef TTF
1639 , _saved_font_files()
1640 #endif
1641 {}
1642 // Disallow copying, since this is a singleton class
1643 FontManager(const FontManager&) = delete;
1644 FontManager& operator=(const FontManager&) = delete;
1645
1646 /*!
1647 * \brief Initialize TrueType fonts
1648 *
1649 * Scan the TTF font directory for TrueType fonts, and add them to the
1650 * current list of fonts.
1651 */
1652 void initialize_ttf();
1653 /*!
1654 * \brief Scan for TrueType fonts
1655 *
1656 * Scan for files matching the glob pattern \a pattern, and if they contain
1657 * a TTF font that supports our character set, add it to our list of known
1658 * fonts.
1659 *
1660 * \param pattern A glob pattern defining the search path
1661 */
1662 void add_ttf_from_pattern(const std::string& pattern);
1663
1664 /*!
1665 * \brief Add options to the configuration
1666 *
1667 * Add options for all fonts to the multi-select variables in the
1668 * configuration window. If the optional parameter \a add_button i \c true,
1669 * buttons for the fonts will immediately be added to the corresponding
1670 * widget.
1671 */
1672 void add_select_options(bool add_button=false);
1673
1674 /*!
1675 * \brief Load a font.
1676 *
1677 * Get the font for font category \a cat and text scale factor \a zoom. If this font fails to
1678 * load, switch to fixed font 1.
1679 *
1680 * \param cat The font category for which to load a font.
1681 * \param text_zoom The scale factor for the text
1682 * \return Reference to the font itself.
1683 */
1684 Font& get(Category cat, float text_zoom);
1685 };
1686
1687 } // namespace eternal_lands
1688
1689 #endif // __cplusplus
1690
1691 #ifdef __cplusplus
1692 extern "C"
1693 {
1694 #endif
1695
1696 //! The font numbers for each font category
1697 extern size_t *font_idxs;
1698 //! The zoom factor for each font category
1699 extern float *font_scales;
1700
1701 #ifdef TTF
1702 #define TTF_DIR_SIZE 256
1703
1704 //! Flag indicating whether to use TTF fonts or not
1705 extern int use_ttf;
1706 //! The path to search for TrueType fonts
1707 extern char ttf_directory[TTF_DIR_SIZE];
1708 #endif // TTF
1709
1710 /*!
1711 * \ingroup text_font
1712 * \brief Initialize the font manager.
1713 *
1714 * This adds the standard fonts bundled with EL to the font manager, and
1715 * if TTF fonts are enabled, scans the TTF path for True Type fonts
1716 * to add as well.
1717 */
1718 int initialize_fonts();
1719
1720 /*!
1721 * \ingroup text_font
1722 * \brief Return the font number of a fixed width font
1723 *
1724 * Return the font number for the \a idx'th fixed width font.
1725 *
1726 * \param idx The number of the font in the list of fixed width fonts only
1727 * \return The index of the font in the list of all fonts
1728 */
1729 size_t get_fixed_width_font_number(size_t idx);
1730
1731 /*!
1732 * \ingroup text_font
1733 * \brief The width of a single character
1734 *
1735 * Return the width of character \a c, including spacing, when drawn
1736 * in the font for category \a cat, at zoom level \a text_zoom.
1737 *
1738 * \param c The character for which to get the width
1739 * \param cat The font category for the font used
1740 * \param text_zoom The scale factor for the text
1741 * \return The width of the character and spacing, in pixels.
1742 */
1743 int get_char_width_zoom(unsigned char c, font_cat cat, float text_zoom);
1744 /*!
1745 * \ingroup text_font
1746 * \brief The maximum width of a single character
1747 *
1748 * Return the maximum a single character can occupy when drawn in the font
1749 * for category \a cat at zoom level \a text_zoom, and include the spacing
1750 * between characters.
1751 *
1752 * \param cat The font category for the font used
1753 * \param text_zoom The scale factor for the text
1754 * \return The maximum character width incuding spacing, in pixels.
1755 */
1756 int get_max_char_width_zoom(font_cat cat, float text_zoom);
1757 /*!
1758 * \ingroup text_font
1759 * \brief Get the average character width, plus spacing
1760 *
1761 * Get an approximation to the average width of a character in the font for
1762 * category \a cat when drawn at zoom level \a text_zoom, including the space
1763 * between characters, for some definition of "average". See the note
1764 * in eternal_lands::Font::average_width_spacing() for some caveats when using
1765 * this function.
1766 *
1767 * \param cat The font category for the font used
1768 * \param text_zoom The zoom factor for drawing the character.
1769 * \return The maximum width of a character including spacing, in pixels.
1770 */
1771 int get_avg_char_width_zoom(font_cat cat, float text_zoom);
1772 /*!
1773 * \ingroup text_font
1774 * \brief The maximum width of a single digit character
1775 *
1776 * Return the maximum a single digit character (0-9) can occupy when drawn
1777 * in the font for category \a cat at zoom level \a text_zoom, and include
1778 * the spacing between characters.
1779 *
1780 * \param cat The font category for the font used
1781 * \param text_zoom The scale factor for the text
1782 * \return The maximum digit character width incuding spacing, in pixels.
1783 */
1784 int get_max_digit_width_zoom(font_cat cat, float text_zoom);
1785 /*!
1786 * \ingroup text_font
1787 * \brief The maximum width of a single name character
1788 *
1789 * Return the maximum pen advancement for a single name character ('0'-'9', 'a'-'z', 'A'-'Z', or '_')
1790 * when drawn in the font for category \a cat at zoom level \a text_zoom, and include the
1791 * spacing between characters.
1792 *
1793 * \param cat The font category for the font used
1794 * \param text_zoom The scale factor for the text
1795 * \return The maximum name character width incuding spacing, in pixels.
1796 */
1797 int get_max_name_width_zoom(font_cat cat, float text_zoom);
1798 /*!
1799 * \ingroup text_font
1800 * \brief Calculate the width of a string
1801 *
1802 * Calculate the width in pixels of the string \a text of length \a len
1803 * when drawn in the font for category \a cat at zoom level \a text_zoom.
1804 * \note This function assumes the string is a single line. Newline
1805 * characters are ignored, and having them in the middle of string will
1806 * result in a too large value for the width.
1807 *
1808 * \param cat The font category for the font used
1809 * \param text The string for which to calculate the length
1810 * \param len The number of bytes in \a text
1811 * \param text_zoom The scale factor for the text
1812 * \return The width of the text in pixels
1813 */
1814 int get_buf_width_zoom(const unsigned char* text, size_t len, font_cat cat, float text_zoom);
1815 /*!
1816 * \ingroup text_font
1817 * \brief Calculate the width of a string
1818 *
1819 * Calculate the width in pixels of the nul-terminated string \a text
1820 * when drawn in the font for category \a cat at zoom level \a text_zoom.
1821 * \note This function assumes the string is a single line. Newline
1822 * characters are ignored, and having them in the middle of string will
1823 * result in a too large value for the width.
1824 *
1825 * \param cat The font category for the font used
1826 * \param text The string for which to calculate the length
1827 * \param text_zoom The scale factor for the text
1828 * \return The width of the text in pixels
1829 */
get_string_width_zoom(const unsigned char * str,font_cat cat,float text_zoom)1830 static __inline__ int get_string_width_zoom(const unsigned char* str, font_cat cat,
1831 float text_zoom)
1832 {
1833 return get_buf_width_zoom(str, strlen((const char*)str), cat, text_zoom);
1834 }
1835 /*!
1836 * \ingroup text_font
1837 * \brief The height of a text line
1838 *
1839 * Return the height of a line of text when drawn in the font for category
1840 * \a cat with scale factor \a text_zoom.
1841 *
1842 * \param cat The font category for the font used
1843 * \param text_zoom The scale factor for the text
1844 * \return The height of the text in pixels
1845 */
1846 int get_line_height(font_cat cat, float text_zoom);
1847 /*!
1848 * \ingroup text_font
1849 * \brief The distance between two lines
1850 *
1851 * Return the distance between two lines of text when drawn in the font for category
1852 * \a cat with scale factor \a text_zoom. This is not necessarily the same as the line
1853 * height.
1854 *
1855 * \param cat The font category for the font used
1856 * \param text_zoom The scale factor for the text
1857 * \return The line distance
1858 */
1859 int get_line_skip(font_cat cat, float text_zoom);
1860 /*!
1861 * \brief Calculate the number of lines that fit.
1862 *
1863 * Return the maximum number of lines that fit in a window of \a height pixels high, when drawing
1864 * text in the font for category \a cat at zoom level \a zoom.
1865 *
1866 * \param max_height The maximum height of the text in pixels
1867 * \param cat The font category for the font used
1868 * \param zoom The zoom factor for drawing the text
1869 * \return The maximum number of lines that fit
1870 */
1871 int get_max_nr_lines(int max_height, font_cat cat, float zoom);
1872 /*!
1873 * \brief Compute the height of a block of text
1874 *
1875 * Compute the height of a block of text of \a nr_lines lines, when drawn in the font for category
1876 * \a cat at zoom level \a zoom.
1877 *
1878 * \param nr_lines The number of lines in the text
1879 * \param cat The font category for the font used
1880 * \param zoom The zoom factor for drawing the text
1881 * \return The height of the text in pixels
1882 */
1883 int get_text_height(int nr_lines, font_cat cat, float zoom);
1884 /*!
1885 * \ingroup text_font
1886 * \brief Calculate the dimensions of a block of text
1887 *
1888 * Calculate the width and height of string \a text of length \a len bytes
1889 * when drawn in the font for category \a cat, with scale factor \a zoom.
1890 * The string may contain multiple lines, the width returned is then the
1891 * width of the widest line.
1892 *
1893 * \param cat The font category for the font used
1894 * \param text The string for which to compute the dimensions
1895 * \param len The number of bytes in \a text
1896 * \param text_zoom The scale factor for the text
1897 * \param width Place to store the calculated width
1898 * \param height Place to store the calculated height
1899 */
1900 void get_buf_dimensions(const unsigned char* text, size_t len, font_cat cat,
1901 float text_zoom, int *width, int *height);
1902
1903 /*!
1904 * \brief Calculate vertical offset of center
1905 *
1906 * Calculate the offset of the center of the characters in \a text with respect to the center
1907 * of the line, when drawn in the font for category \a cat at zoom level \a text_zoom. Subtract the
1908 * result of this function from the \c y coordinate you wish to center around, to center the
1909 * content of \a text around this position.
1910 *
1911 * \param cat The font category for the font used
1912 * \param text The string for which to compute center offset
1913 * \param len The number of bytes in \a text
1914 * \param text_zoom The scale factor for the text
1915 * \return The number of pixels between the center of the line and the center of \a text.
1916 */
1917 int get_center_offset(const unsigned char* text, size_t len, font_cat cat, float text_zoom);
1918 /*!
1919 * \brief Get vertical coordinates
1920 *
1921 * Get the minimum and maximum offsets of the characters in \a text with respect to the top of
1922 * the text line, when drawing the text in the font for category \a cat at zoom level \a zoom.
1923 *
1924 * \param text The text to get the vertical offsets for
1925 * \param len The number of characters in \a text
1926 * \param cat The font category for the font used
1927 * \param text_zoom The scale factor for the text
1928 * \return The offsets of the top and bottom of the text
1929 */
1930 void get_top_bottom(const unsigned char* text, size_t len, font_cat cat, float text_zoom,
1931 int *top, int *bottom);
1932
1933 /*!
1934 * \ingroup text_font
1935 * \brief Recompute where the line breaks in a string should occur
1936 *
1937 * Recomputes the positions in string \a text where line breaks should be placed,
1938 * when drawn in the font for category \a cat at zoom level \a text_zoom such
1939 * that the string fits into a window of width \a width pixels. This inserts
1940 * \c '\\r' characters at the positions in \a text where the line should be broken.
1941 * Parameters \a len and \a size are the current and maximum number of bytes in \a text,
1942 * respectively. If \a cursor is not \c NULL, it should point to the offset of the
1943 * cursor position in the text; it will be updated as new line breaks are inserted.
1944 * If \a max_line_width is not \c NULL, it can be used to retrieve the largest width
1945 * in pixels of the lines in \a text after rewrapping.
1946 *
1947 * \param text the string
1948 * \param len the actual length of the string
1949 * \param size the maximum number of bytes in \a text
1950 * \param cat the font category in which the string is to be drawn
1951 * \param text_zoom the scale factor for the text
1952 * \param width the allowed width of a line of text
1953 * \param cursor pointer to the cursor position, or NULL if not used
1954 * \param max_line_width pointer the maximum line length after wrapping, or NULL if not used
1955 *
1956 * \return The wrapped text, and the new number of lines in the text
1957 */
1958 int reset_soft_breaks(unsigned char *text, int len, int size, font_cat cat,
1959 float text_zoom, int width, int *cursor, int *max_line_width);
1960 /*!
1961 * \ingroup text_font
1962 * \brief Wrap a text so that it fits into a window
1963 *
1964 * Create a version of \a text with newline characters inserted so that the
1965 * line length does not exceeed \a width pixels when drawn in a small font for
1966 * the UI_FONT category, at zoom level \a zoom, and store it in \a buffer. The
1967 * parameter \a color is an index in colors_list; it will be converted to a
1968 * color character which is inserted in front of the text in \a buffer.
1969 * \warning No check is made if \a buffer is large enough to hold the output
1970 * text, the caller needs to ensure this.
1971 *
1972 * \param color The color with which the text should be drawn
1973 * \param text The text to wrap
1974 * \param len The number of bytes in text
1975 * \param width The maximum allowed width in pixels of a line of text
1976 * \param buffer Output buffer in which the result is stored
1977 * \param text_zoom Zoom factor for the text (on top of using small text)
1978 */
1979 void put_small_colored_text_in_box_zoomed(int color,
1980 const unsigned char* text, int len, int width,
1981 unsigned char* buffer, float text_zoom);
1982 /*!
1983 * \ingroup text_font
1984 * \brief Wrap a text so that it fits into a window
1985 *
1986 * Create a version of \a text with newline characters inserted so that the
1987 * line length does not exceeed \a width pixels when drawn in a small font for
1988 * the UI_FONT category, at zoom level \a zoom, and store it in \a buffer. The
1989 * text will be drawn in white.
1990 * \warning No check is made if \a buffer is large enough to hold the output
1991 * text, the caller needs to ensure this.
1992 *
1993 * \param text The text to wrap
1994 * \param len The number of bytes in text
1995 * \param width The maximum allowed width in pixels of a line of text
1996 * \param buffer Output buffer in which the result is stored
1997 * \param text_zoom Zoom factor for the text (on top of using small text)
1998 */
put_small_text_in_box_zoomed(const unsigned char * text,int len,int width,unsigned char * buffer,float text_zoom)1999 static __inline__ void put_small_text_in_box_zoomed (const unsigned char* text,
2000 int len, int width, unsigned char* buffer, float text_zoom)
2001 {
2002 put_small_colored_text_in_box_zoomed(c_grey1, text, len, width, buffer, text_zoom);
2003 }
2004
2005 /*!
2006 * \ingroup text_font
2007 * \brief Enumeration for text drawing options
2008 *
2009 * Various text drawing options can be passed to \ref draw text, specified by a selector from this
2010 * enumeration followed by one or more arguments.
2011 */
2012 typedef enum
2013 {
2014 //! Set the maximum width, followed by \c int
2015 TDO_MAX_WIDTH,
2016 //! Set the maximum number of lines, followed by \c int
2017 TDO_MAX_LINES,
2018 //! Scale factor for the text, followed by \c float
2019 TDO_ZOOM,
2020 //! Scale factor for the spacing between lines, followed by \c float
2021 TDO_LINE_SPACING,
2022 //! Horizontal alignment, followed by a \c hor_alignment
2023 TDO_ALIGNMENT,
2024 //! Vertical alignment, followed by a \c ver_alignment
2025 TDO_VERTICAL_ALIGNMENT,
2026 //! Draw the text with a shadow in the background color, followed by \c bool
2027 TDO_SHADOW,
2028 //! Foreground color of the text, followed by 3 \c floats
2029 TDO_FOREGROUND,
2030 //! Background color of the text, followed by 3 \c floats
2031 TDO_BACKGROUND,
2032 //! Selection color of the text, followed by 3 \c floats
2033 TDO_SELECTION,
2034 //! Ignor color characters in the text, followed by \c bool
2035 TDO_IGNORE_COLOR,
2036 //! Draw the string as help text, with a semi-transparent background, followed by \c bool
2037 TDO_HELP,
2038 //! Indicate clipped text with ellipsis, followed by \c bool
2039 TDO_ELLIPSIS,
2040 //! Shrink text if it is too wide, followed by \a bool
2041 TDO_SHRINK_TO_FIT,
2042 //! Start index of the selected text, followed by \c int
2043 TDO_SEL_BEGIN,
2044 //! End index of the selected text, followed by \c int
2045 TDO_SEL_END,
2046 //! End of text draw options, should always be last
2047 TDO_END
2048 } text_draw_option_sel;
2049
2050 /*!
2051 * \ingroup text_font
2052 * \brief Draw a text string
2053 *
2054 * Draw the text in the first \a len bytes of \a text, starting at position \a x, \a y on the
2055 * screen, using the font for category \a cat, with formatting options \a options. The options
2056 * should be a (possbily empty) list of option selectors of type \ref text_draw_option_sel, each
2057 * followed by the arguments for that particular selector, and should end with \ref TDO_END.
2058 *
2059 * \param x The left coordinate of the drawn text
2060 * \param y The top coordinate of the drawn text
2061 * \param text The text to draw
2062 * \param len The number of bytes in \a text
2063 * \param cat The font category for the text
2064 * \param options Formatting options for the text
2065 */
2066 void vdraw_text(int x, int y, const unsigned char* text, size_t len, font_cat cat, va_list options);
2067 /*!
2068 * \ingroup text_font
2069 * \brief Draw a text string
2070 *
2071 * Draw the text in the first \a len bytes of \a text, starting at position \a x, \a y on the
2072 * screen, using the font for category \a cat, with formatting options \a options. Formatting
2073 * options for the text can be given after \a cat; the list of formatting options should always
2074 * end with \ref TDO_END.
2075 * \note Even when no formatting options are given, \ref TDO_END should be passed as the only
2076 * extra parameter to indicate the end of the options list.
2077 *
2078 * \param x The left coordinate of the drawn text
2079 * \param y The top coordinate of the drawn text
2080 * \param text The text to draw
2081 * \param len The number of bytes in \a text
2082 * \param cat The font category for the text
2083 * \param options Formatting options for the text
2084 * \note The type of \a cat is \c int here instead of \c font_cat. This is on purpose, as using a
2085 * type that undergoes default argument promotion as the last argument before the variable
2086 * argument list results in undefined behaviour.
2087 */
draw_text(int x,int y,const unsigned char * text,size_t len,int cat,...)2088 static __inline__ void draw_text(int x, int y, const unsigned char* text, size_t len, int cat, ...)
2089 {
2090 va_list ap;
2091 va_start(ap, cat);
2092 vdraw_text(x, y, text, len, (font_cat)cat, ap);
2093 va_end(ap);
2094 }
2095
2096 /*!
2097 * \ingroup text_font
2098 * \brief Draw a text string
2099 *
2100 * Draw the text in the nul-terminated buffer \a text, starting at position
2101 * \a x, \a y on the screen, using the font for category \a cat. Options \a max_width and
2102 * \a max_lines specify the maximum width of the text and maximum number of lines
2103 * drawn respectively. Text outside these boundaries will not be drawn. The text
2104 * will be drawn in the default foreground color.
2105 *
2106 * \param x The left coordinate of the drawn text
2107 * \param y The top coordinate of the drawn text
2108 * \param text The text to draw
2109 * \param max_width The maximum width in pixels of the text
2110 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2111 * \param cat The font category for the text
2112 * \param text_zoom Scale factor for the text size
2113 */
draw_string_zoomed_width_font(int x,int y,const unsigned char * text,int max_width,int max_lines,font_cat cat,float text_zoom)2114 static __inline__ void draw_string_zoomed_width_font(int x, int y, const unsigned char *text,
2115 int max_width, int max_lines, font_cat cat, float text_zoom)
2116 {
2117 draw_text(x, y, text, strlen((const char*)text), cat, TDO_MAX_WIDTH, max_width,
2118 TDO_MAX_LINES, max_lines, TDO_ZOOM, text_zoom, TDO_END);
2119 }
2120 /*!
2121 * \ingroup text_font
2122 * \brief Draw a text string
2123 *
2124 * Draw the text in the nul-terminated buffer \a text, centered around position
2125 * \a x, \a y on the screen, using the font for the UI_FONT category. The centering is
2126 * done such that the bytes up to \a center_idx are drawn left of \a x, and the
2127 * bytes from \a center_idx onward are drawn to the right of \a x.
2128 *
2129 * \param x The x coordinate of the center of drawn text
2130 * \param y The top coordinate of the drawn text
2131 * \param text The text to draw
2132 * \param center_idx The index of the character around which the centering is done
2133 * \param text_zoom Scale factor for the text size
2134 */
2135 void draw_string_zoomed_centered_around(int x, int y, const unsigned char *text, int center_idx,
2136 float text_zoom);
2137 /*!
2138 * \ingroup text_font
2139 * \brief Draw a text string
2140 *
2141 * Draw the text in the nul-terminated buffer \a text, starting at position
2142 * \a x, \a y on the screen, using the font for the UI_FONT category. The option
2143 * \a max_lines specifies the maximum number of lines drawn, any text after
2144 * this line will not be drawn. The text will be drawn in the default foreground
2145 * color.
2146 *
2147 * \param x The left coordinate of the drawn text
2148 * \param y The top coordinate of the drawn text
2149 * \param text The text to draw
2150 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2151 * \param text_zoom Scale factor for the text size
2152 */
draw_string_zoomed(int x,int y,const unsigned char * text,int max_lines,float text_zoom)2153 static __inline__ void draw_string_zoomed(int x, int y, const unsigned char* text,
2154 int max_lines, float text_zoom)
2155 {
2156 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2157 TDO_ZOOM, text_zoom, TDO_END);
2158 }
2159 /*!
2160 * \ingroup text_font
2161 * \brief Draw a text string
2162 *
2163 * Draw the text in the nul-terminated buffer \a text, centered around position
2164 * \a x, \a y on the screen, using the font for the UI_FONT category. The option
2165 * \a max_lines specifies the maximum number of lines drawn, any text after
2166 * this line will not be drawn. The text will be drawn in the default foreground
2167 * color.
2168 *
2169 * \param x The x coordinate of the center of drawn text
2170 * \param y The top coordinate of the drawn text
2171 * \param text The text to draw
2172 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2173 * \param text_zoom Scale factor for the text size
2174 */
draw_string_zoomed_centered(int x,int y,const unsigned char * text,int max_lines,float text_zoom)2175 static __inline__ void draw_string_zoomed_centered(int x, int y, const unsigned char *text,
2176 int max_lines, float text_zoom)
2177 {
2178 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2179 TDO_ZOOM, text_zoom, TDO_ALIGNMENT, CENTER, TDO_END);
2180 }
2181 /*!
2182 * \ingroup text_font
2183 * \brief Draw a text string
2184 *
2185 * Draw the text in the nul-terminated buffer \a text, starting at position
2186 * \a x, \a y on the screen, using the font for the UI_FONT category. The string
2187 * is drawn in the color (\a fr, \a fg, \a fb), with a background shadow in
2188 * the color (\a br, \a bg, \a bb). The option \a max_lines specifies the maximum
2189 * number of lines drawn, any text after this line will not be drawn.
2190 *
2191 *
2192 * \param x The left coordinate of the drawn text
2193 * \param y The top coordinate of the drawn text
2194 * \param text The text to draw
2195 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2196 * \param fr Red component of the foreground color
2197 * \param fg Green component of the foreground color
2198 * \param fb Blue component of the foreground color
2199 * \param br Red component of the background color
2200 * \param bg Green component of the background color
2201 * \param bb Blue component of the background color
2202 * \param text_zoom Scale factor for the text size
2203 */
draw_string_shadowed_zoomed(int x,int y,const unsigned char * text,int max_lines,float fr,float fg,float fb,float br,float bg,float bb,float text_zoom)2204 static __inline__ void draw_string_shadowed_zoomed(int x, int y, const unsigned char* text,
2205 int max_lines, float fr, float fg, float fb, float br, float bg, float bb, float text_zoom)
2206 {
2207 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2208 TDO_SHADOW, 1, TDO_FOREGROUND, fr, fg, fb, TDO_BACKGROUND, br, bg, bb, TDO_ZOOM, text_zoom,
2209 TDO_END);
2210 }
2211 /*!
2212 * \ingroup text_font
2213 * \brief Draw a text string
2214 *
2215 * Draw the text in the nul-terminated buffer \a text, centered around position
2216 * \a x, \a y on the screen, using the font for the UI_FONT category. The string
2217 * is drawn in the color (\a fr, \a fg, \a fb), with a background shadow in
2218 * the color (\a br, \a bg, \a bb). The option \a max_lines specifies the maximum
2219 * number of lines drawn, any text after this line will not be drawn.
2220 *
2221 *
2222 * \param x The x coordinate of the center of drawn text
2223 * \param y The top coordinate of the drawn text
2224 * \param text The text to draw
2225 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2226 * \param fr Red component of the foreground color
2227 * \param fg Green component of the foreground color
2228 * \param fb Blue component of the foreground color
2229 * \param br Red component of the background color
2230 * \param bg Green component of the background color
2231 * \param bb Blue component of the background color
2232 * \param text_zoom Scale factor for the text size
2233 */
draw_string_shadowed_zoomed_centered(int x,int y,const unsigned char * text,int max_lines,float fr,float fg,float fb,float br,float bg,float bb,float text_zoom)2234 static __inline__ void draw_string_shadowed_zoomed_centered(int x, int y, const unsigned char* text,
2235 int max_lines, float fr, float fg, float fb, float br, float bg, float bb, float text_zoom)
2236 {
2237 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2238 TDO_SHADOW, 1, TDO_FOREGROUND, fr, fg, fb, TDO_BACKGROUND, br, bg, bb, TDO_ZOOM, text_zoom,
2239 TDO_ALIGNMENT, CENTER, TDO_END);
2240 }
2241 /*!
2242 * \ingroup text_font
2243 * \brief Draw a text string
2244 *
2245 * Draw the text in the nul-terminated buffer \a text, starting at position
2246 * \a x, \a y on the screen, using the font for category \a cat. If a line
2247 * cannot fit within the maximum width \a max_width, it will be truncated and
2248 * an ellipsis is added. The option \a max_lines specifies the maximum
2249 * number of lines drawn, any text after this line will not be drawn.
2250 *
2251 * \param x The left coordinate of the drawn text
2252 * \param y The top coordinate of the drawn text
2253 * \param text The text to draw
2254 * \param max_width The maximum width in pixels of the text
2255 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2256 * \param cat The font category for the text
2257 * \param text_zoom Scale factor for the text size
2258 */
draw_string_zoomed_ellipsis_font(int x,int y,const unsigned char * text,int max_width,int max_lines,font_cat cat,float text_zoom)2259 static __inline__ void draw_string_zoomed_ellipsis_font(int x, int y, const unsigned char *text,
2260 int max_width, int max_lines, font_cat cat, float text_zoom)
2261 {
2262 draw_text(x, y, text, strlen((const char*)text), cat, TDO_MAX_WIDTH, max_width,
2263 TDO_MAX_LINES, max_lines, TDO_ZOOM, text_zoom, TDO_ELLIPSIS, 1, TDO_END);
2264 }
2265
2266 //! Analogue of draw_string_zoomed(), for small text size
draw_string_small_zoomed(int x,int y,const unsigned char * text,int max_lines,float text_zoom)2267 static __inline__ void draw_string_small_zoomed(int x, int y,
2268 const unsigned char* text, int max_lines, float text_zoom)
2269 {
2270 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2271 TDO_ZOOM, text_zoom * DEFAULT_SMALL_RATIO, TDO_END);
2272 }
2273 /*!
2274 * \ingroup text_font
2275 * \brief Draw a text string
2276 *
2277 * Draw the text in the nul-terminated buffer \a text, right aligned to position
2278 * \a x, \a y on the screen, using the small font for the UI_FONT category. The option
2279 * \a max_lines specifies the maximum number of lines drawn, any text after
2280 * this line will not be drawn. The text will be drawn in the default foreground
2281 * color.
2282 *
2283 * \param x The right coordinate of the drawn text
2284 * \param y The top coordinate of the drawn text
2285 * \param text The text to draw
2286 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2287 * \param text_zoom Scale factor for the text size
2288 */
draw_string_small_zoomed_right(int x,int y,const unsigned char * text,int max_lines,float text_zoom)2289 static __inline__ void draw_string_small_zoomed_right(int x, int y,
2290 const unsigned char* text, int max_lines, float text_zoom)
2291 {
2292 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2293 TDO_ZOOM, text_zoom * DEFAULT_SMALL_RATIO, TDO_ALIGNMENT, RIGHT, TDO_END);
2294 }
2295 //! Analogue of draw_string_zoomed_centered(), for small text size
draw_string_small_zoomed_centered(int x,int y,const unsigned char * text,int max_lines,float text_zoom)2296 static __inline__ void draw_string_small_zoomed_centered(int x, int y,
2297 const unsigned char* text, int max_lines, float text_zoom)
2298 {
2299 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2300 TDO_ZOOM, text_zoom * DEFAULT_SMALL_RATIO, TDO_ALIGNMENT, CENTER, TDO_END);
2301 }
2302 //! Analogue of draw_string_zoomed_centered_around(), for small text size
draw_string_small_zoomed_centered_around(int x,int y,const unsigned char * text,int center_idx,float text_zoom)2303 static __inline__ void draw_string_small_zoomed_centered_around(int x, int y,
2304 const unsigned char *text, int center_idx, float text_zoom)
2305 {
2306 draw_string_zoomed_centered_around(x, y, text, center_idx, text_zoom * DEFAULT_SMALL_RATIO);
2307 }
2308 //! Analogue of draw_string_shadowed_zoomed(), for small text size
draw_string_small_shadowed_zoomed(int x,int y,const unsigned char * text,int max_lines,float fr,float fg,float fb,float br,float bg,float bb,float text_zoom)2309 static __inline__ void draw_string_small_shadowed_zoomed(int x, int y,
2310 const unsigned char* text, int max_lines, float fr, float fg, float fb,
2311 float br, float bg, float bb, float text_zoom)
2312 {
2313 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2314 TDO_SHADOW, 1, TDO_FOREGROUND, fr, fg, fb, TDO_BACKGROUND, br, bg, bb,
2315 TDO_ZOOM, text_zoom * DEFAULT_SMALL_RATIO, TDO_END);
2316 }
2317 /*!
2318 * \ingroup text_font
2319 * \brief Draw a text string
2320 *
2321 * Draw the text in the nul-terminated buffer \a text, right aligned to position
2322 * \a x, \a y on the screen, using the small font for the UI_FONT category. The string
2323 * is drawn in the color (\a fr, \a fg, \a fb), with a background shadow in
2324 * the color (\a br, \a bg, \a bb). The option \a max_lines specifies the maximum
2325 * number of lines drawn, any text after this line will not be drawn.
2326 *
2327 *
2328 * \param x The right coordinate of the drawn text
2329 * \param y The top coordinate of the drawn text
2330 * \param text The text to draw
2331 * \param max_lines The maximum number of lines to draw, or 0 for no limit
2332 * \param fr Red component of the foreground color
2333 * \param fg Green component of the foreground color
2334 * \param fb Blue component of the foreground color
2335 * \param br Red component of the background color
2336 * \param bg Green component of the background color
2337 * \param bb Blue component of the background color
2338 * \param text_zoom Scale factor for the text size
2339 */
draw_string_small_shadowed_zoomed_right(int x,int y,const unsigned char * text,int max_lines,float fr,float fg,float fb,float br,float bg,float bb,float text_zoom)2340 static __inline__ void draw_string_small_shadowed_zoomed_right(int x, int y,
2341 const unsigned char* text, int max_lines, float fr, float fg, float fb,
2342 float br, float bg, float bb, float text_zoom)
2343 {
2344 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_LINES, max_lines,
2345 TDO_SHADOW, 1, TDO_FOREGROUND, fr, fg, fb, TDO_BACKGROUND, br, bg, bb,
2346 TDO_ZOOM, text_zoom * DEFAULT_SMALL_RATIO, TDO_ALIGNMENT, RIGHT, TDO_END);
2347 }
2348
2349 /*!
2350 * \ingroup text_font
2351 * \brief Draw a help message
2352 *
2353 * Shows the help message \a text centered horizontally around position
2354 * (\a x, \a y) in text color (\a r, \a g, \a b), with text scale factor
2355 * \a text_zoom. The message is drawn on a semi-transparent background.
2356 *
2357 * \param text The help text to display
2358 * \param x The x-coordinate of the center of the text
2359 * \param y The y-coordinate of the top of text text
2360 * \param r The red component of the text color
2361 * \param g The green component of the text color
2362 * \param b The blue component of the text color
2363 * \param text_zoom The scale factor for the text size
2364 */
show_help_colored_scaled_centered(const unsigned char * text,int x,int y,float r,float g,float b,float text_zoom)2365 static __inline__ void show_help_colored_scaled_centered(const unsigned char *text, int x, int y,
2366 float r, float g, float b, float text_zoom)
2367 {
2368 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_WIDTH, window_width - 80,
2369 TDO_HELP, 1, TDO_FOREGROUND, r, g, b, TDO_ZOOM, text_zoom, TDO_ALIGNMENT, CENTER, TDO_END);
2370 }
2371 /*!
2372 * \ingroup text_font
2373 * \brief Draw a help message
2374 *
2375 * Shows the help message \a text right-aligned to position (\a x, \a y)
2376 * in text color (\a r, \a g, \a b), with text scale factor \a text_zoom.
2377 * The message is drawn on a semi-transparent background.
2378 *
2379 * \param text The help text to display
2380 * \param x The x-coordinate of the right side of the text
2381 * \param y The y-coordinate of the top of text text
2382 * \param r The red component of the text color
2383 * \param g The green component of the text color
2384 * \param b The blue component of the text color
2385 * \param text_zoom The scale factor for the text size
2386 */
show_help_colored_scaled_right(const unsigned char * text,int x,int y,float r,float g,float b,float text_zoom)2387 static __inline__ void show_help_colored_scaled_right(const unsigned char *text, int x, int y,
2388 float r, float g, float b, float text_zoom)
2389 {
2390 draw_text(x, y, text, strlen((const char*)text), UI_FONT, TDO_MAX_WIDTH, window_width - 80,
2391 TDO_HELP, 1, TDO_FOREGROUND, r, g, b, TDO_ZOOM, text_zoom, TDO_ALIGNMENT, RIGHT, TDO_END);
2392 }
2393 /*!
2394 * \ingroup text_font
2395 * \brief Shows a help message in small font
2396 *
2397 * Shows the help message \a text at position (\a x, \a y) using a small font
2398 * size. The message is drawn on a semi-transparent background.
2399 *
2400 * \param text the help message to show
2401 * \param x the x coordinate of the left of the help message
2402 * \param y the y coordinate of the top of the help message
2403 * \param text_zoom the scale for the text size
2404 */
show_help(const char * text,int x,int y,float text_zoom)2405 static __inline__ void show_help(const char *text, int x, int y, float text_zoom)
2406 {
2407 draw_text(x, y, (const unsigned char*)text, strlen(text), UI_FONT,
2408 TDO_MAX_WIDTH, window_width - 80, TDO_HELP, 1, TDO_FOREGROUND, 1.0, 1.0, 1.0,
2409 TDO_ZOOM, text_zoom * DEFAULT_SMALL_RATIO, TDO_END);
2410 }
2411 /*!
2412 * \ingroup text_font
2413 * \brief Shows a help message in normal font
2414 *
2415 * Shows the help message \a text at position (\a x, \a y) using the normal
2416 * font size. The message is drawn on a semi-transparent background.
2417 *
2418 * \param text the help message to show
2419 * \param x the x coordinate of the left of the help message
2420 * \param y the y coordinate of top of the help message
2421 * \param text_zoom the scale for the text size
2422 */
show_help_big(const char * text,int x,int y,float text_zoom)2423 static __inline__ void show_help_big(const char *text, int x, int y, float text_zoom)
2424 {
2425 draw_text(x, y, (const unsigned char*)text, strlen(text), UI_FONT,
2426 TDO_MAX_WIDTH, window_width - 80,TDO_HELP, 1, TDO_FOREGROUND, 1.0, 1.0, 1.0,
2427 TDO_ZOOM, text_zoom, TDO_END);
2428 }
2429
2430 /*!
2431 * \ingroup text_font
2432 * \brief Draw messages in a buffer to the screen
2433 *
2434 * Draws the messages in buffer \a msgs to the screen, starting with character
2435 * \a offset_start in message number \a msg_start.
2436 *
2437 * \param x x coordinate of the position to start drawing
2438 * \param y y coordinate of the position to start drawing
2439 * \param msgs the message buffer
2440 * \param msgs_size the total number of messages that \a msgs can hold
2441 * \param filter draw only messages in channel \a filter. Choose
2442 * FILTER_ALL for displaying all messages
2443 * \param msg_start index of the first message to display
2444 * \param offset_start the first character in message \a msg_start to display
2445 * \param cursor if >= 0, the position at which to draw the cursor
2446 * \param width the width of the output window
2447 * \param height the height of the output window
2448 * \param cat the font category for the font used to draw the messages
2449 * \param text_zoom the scale factor for the text size
2450 * \param[in,out] select information about current selection. draw_messages()
2451 * fills the select->lines array.
2452 */
2453 void draw_messages(int x, int y, text_message *msgs, int msgs_size, Uint8 filter,
2454 int msg_start, int offset_start, int cursor, int width, int height,
2455 font_cat cat, float text_zoom, select_info* select);
2456 /*!
2457 * \ingroup text_font
2458 * \brief Draw the console separator
2459 *
2460 * When there are more messages than can fit on a single screen, the user can
2461 * scroll up to see the previous messages. When they do, a separator is
2462 * drawn by this function to indicate that more messages follow.
2463 *
2464 * \param x_space Horizontal space tokeep free on either side
2465 * \param y Vertical position at which the line should be drawn
2466 * \param width The width of the console window
2467 * \param text_zoom The zoom level of the console text
2468 */
2469 void draw_console_separator(int x_space, int y, int width, float text_zoom);
2470 #ifdef ELC
2471 #ifndef MAP_EDITOR2
2472 void draw_ortho_ingame_string(float x, float y, float z, const unsigned char *text, int max_lines,
2473 font_cat cat, float zoom_x, float zoom_y);
2474 #endif // !MAP_EDITOR2
2475 #endif // ELC
2476
2477 /*!
2478 * \ingroup text_font
2479 * \brief Set the config font
2480 *
2481 * Copy the current font index and scale of the UI_FONT category to that
2482 * of the CONFIG_FONT category. This allows us to change the UI font
2483 * without changing the way the options window is drawn, and hopefully
2484 * stops the user from then being unable to change the font back.
2485 */
2486 void set_config_font();
2487
2488 /*!
2489 * \ingroup text_font
2490 * \brief whether a glyph is defined for character \a c, i.e. if it is printable
2491 */
2492 int has_glyph(unsigned char c);
2493
2494 #ifdef TTF
2495 //! Disable TrueType fonts, allowing bundled fonts only.
2496 void disable_ttf(void);
2497 //! Enable TrueTyoe fonts, restoring previous font indices if possible
2498 void enable_ttf(void);
2499 #endif
2500
2501 #ifdef __cplusplus
2502 } // extern "C"
2503 #endif
2504
2505 #endif // NEW_FONT_H
2506