The Battle for Wesnoth  1.17.10+dev
sdl_ttf_compat.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2021 - 2022
3  by Iris Morelle <shadowm@wesnoth.org>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include "font/sdl_ttf_compat.hpp"
17 
18 #include "draw.hpp"
19 #include "font/standard_colors.hpp"
20 #include "log.hpp"
21 #include "sdl/point.hpp"
22 #include "sdl/texture.hpp"
23 #include "sdl/utils.hpp"
25 #include "tooltips.hpp"
26 
27 static lg::log_domain log_font("font");
28 #define DBG_FT LOG_STREAM(debug, log_font)
29 #define LOG_FT LOG_STREAM(info, log_font)
30 #define WRN_FT LOG_STREAM(warn, log_font)
31 #define ERR_FT LOG_STREAM(err, log_font)
32 
33 namespace font {
34 
35 namespace {
36 
37 pango_text& private_renderer()
38 {
39  // Use a separate renderer for GUI1 in case of shenanigans.
40  static pango_text text_renderer;
41  return text_renderer;
42 }
43 
44 }
45 
46 texture pango_render_text(const std::string& text, int size, const color_t& color, font::pango_text::FONT_STYLE style, bool use_markup, int max_width)
47 {
48  auto& ptext = private_renderer();
49 
50  ptext.set_text(text, use_markup);
51  ptext.set_family_class(font::FONT_SANS_SERIF)
52  .set_font_size(size)
53  .set_font_style(style)
54  .set_maximum_height(-1, false)
55  .set_foreground_color(color)
56  .set_maximum_width(max_width)
57  .set_ellipse_mode(max_width > 0 ? PANGO_ELLIPSIZE_END : PANGO_ELLIPSIZE_NONE);
58 
59  return ptext.render_and_get_texture();
60 }
61 
62 std::pair<int, int> pango_line_size(const std::string& line, int font_size, font::pango_text::FONT_STYLE font_style)
63 {
64  auto& ptext = private_renderer();
65 
66  ptext.set_text(line, false);
67  ptext.set_family_class(font::FONT_SANS_SERIF)
68  .set_font_size(font_size)
69  .set_font_style(font_style)
70  .set_maximum_height(-1, false)
71  .set_maximum_width(-1)
72  .set_ellipse_mode(PANGO_ELLIPSIZE_NONE);
73 
74  auto s = ptext.get_size();
75  return { s.x, s.y };
76 }
77 
78 std::string pango_line_ellipsize(const std::string& text, int font_size, int max_width, font::pango_text::FONT_STYLE font_style)
79 {
80  if(pango_line_width(text, font_size, font_style) <= max_width) {
81  return text;
82  }
83  if(pango_line_width(font::ellipsis, font_size, font_style) > max_width) {
84  return "";
85  }
86 
87  std::string current_substring;
88 
89  try {
90  utf8::iterator itor(text);
91  for(; itor != utf8::iterator::end(text); ++itor) {
92  std::string tmp = current_substring;
93  tmp.append(itor.substr().first, itor.substr().second);
94 
95  if(pango_line_width(tmp + font::ellipsis, font_size, font_style) > max_width) {
96  return current_substring + font::ellipsis;
97  }
98 
99  current_substring = std::move(tmp);
100  }
101  } catch(const utf8::invalid_utf8_exception&) {
102  WRN_FT << "Invalid UTF-8 string: \"" << text << "\"";
103  return "";
104  }
105 
106  return text; // Should not happen
107 }
108 
109 std::string pango_word_wrap(const std::string& unwrapped_text, int font_size, int max_width, int max_height, int max_lines, bool /*partial_line*/)
110 {
111  // FIXME: what the hell does partial_line do in the SDL_ttf version?
112 
113  if(max_lines == 0) {
114  return "";
115  }
116 
117  auto& ptext = private_renderer();
118 
119  ptext.set_text(unwrapped_text, false);
120  ptext.set_family_class(font::FONT_SANS_SERIF)
121  .set_font_size(font_size)
122  .set_font_style(font::pango_text::STYLE_NORMAL)
123  .set_maximum_height(max_height, true)
124  .set_maximum_width(max_width)
125  .set_ellipse_mode(PANGO_ELLIPSIZE_NONE);
126 
127  std::string res;
128  const auto& lines = ptext.get_lines();
129 
130  for(const auto& line : lines) {
131  if(!res.empty())
132  res += '\n';
133  res += line;
134  if(--max_lines == 0)
135  break;
136  }
137 
138  return res;
139 }
140 
141 rect pango_draw_text(bool actually_draw, const rect& area, int size, const color_t& color, const std::string& text, int x, int y, bool use_tooltips, pango_text::FONT_STYLE style)
142 {
143  auto& ptext = private_renderer();
144 
145  ptext.set_text(text, false);
146  ptext.set_family_class(font::FONT_SANS_SERIF)
147  .set_font_size(size)
148  .set_font_style(style)
149  .set_maximum_width(-1)
150  .set_foreground_color(color)
151  .set_ellipse_mode(PANGO_ELLIPSIZE_END);
152 
153  if(!area.empty()) {
154  ptext.set_maximum_height(area.h, true);
155  }
156 
157  auto extents = ptext.get_size();
158  bool ellipsized = false;
159 
160  if(!area.empty() && extents.x > area.w) {
161  ptext.set_maximum_width(area.w);
162  ellipsized = true;
163  }
164 
165  auto t = ptext.render_and_get_texture();
166 
167  SDL_Rect res = {x, y, t.w(), t.h()};
168 
169  if(actually_draw) {
170  draw::blit(t, res);
171  }
172 
173  if(ellipsized && use_tooltips) {
174  tooltips::add_tooltip(res, text);
175  }
176 
177  return res;
178 }
179 
180 } // end namespace font
Drawing functions, for drawing things on the screen.
std::string pango_line_ellipsize(const std::string &text, int font_size, int max_width, font::pango_text::FONT_STYLE font_style)
If the text exceeds the specified max width, end it with an ellipsis (...)
int add_tooltip(const SDL_Rect &origin, const std::string &message, const std::string &action)
Definition: tooltips.cpp:237
Collection of helper functions relating to Pango formatting.
std::pair< int, int > pango_line_size(const std::string &line, int font_size, font::pango_text::FONT_STYLE font_style)
Determine the width and height of a line of text given a certain font size.
#define WRN_FT
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:32
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
const std::string ellipsis
Definition: constants.cpp:39
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:58
const std::pair< typename string_type::const_iterator, typename string_type::const_iterator > & substr() const
std::string pango_word_wrap(const std::string &unwrapped_text, int font_size, int max_width, int max_height, int max_lines, bool)
Uses Pango to word wrap text.
bool empty() const
False if both w and h are > 0, true otherwise.
Definition: rect.cpp:49
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:171
Thrown by operations encountering invalid UTF-8 data.
static map_location::DIRECTION s
rect pango_draw_text(bool actually_draw, const rect &area, int size, const color_t &color, const std::string &text, int x, int y, bool use_tooltips, pango_text::FONT_STYLE style)
Draws text on the screen.
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:46
static iterator_base end(const string_type &str)
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:301
texture pango_render_text(const std::string &text, int size, const color_t &color, font::pango_text::FONT_STYLE style, bool use_markup, int max_width)
Returns a SDL texture containing the rendered text.
double t
Definition: astarsearch.cpp:65
Standard logging facilities (interface).
static lg::log_domain log_font("font")
Transitional API for porting SDL_ttf-based code to Pango.
int pango_line_width(const std::string &line, int font_size, font::pango_text::FONT_STYLE font_style=font::pango_text::STYLE_NORMAL)
Determine the width of a line of text given a certain font size.