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