The Battle for Wesnoth  1.17.10+dev
canvas.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 - 2022
3  by Mark de Wever <koraq@xs4all.nl>
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 /**
17  * @file
18  * Implementation of canvas.hpp.
19  */
20 
21 #define GETTEXT_DOMAIN "wesnoth-lib"
22 
23 #include "gui/core/canvas.hpp"
25 
26 #include "draw.hpp"
27 #include "font/text.hpp"
28 #include "formatter.hpp"
29 #include "gettext.hpp"
31 #include "gui/core/log.hpp"
32 #include "gui/widgets/helper.hpp"
33 #include "picture.hpp"
34 #include "sdl/point.hpp"
35 #include "sdl/rect.hpp"
36 #include "sdl/texture.hpp"
37 #include "sdl/utils.hpp" // blur_surface
38 #include "video.hpp" // read_pixels_low_res, only used for blurring
39 #include "wml_exception.hpp"
40 
41 namespace gui2
42 {
43 
44 /***** ***** ***** ***** ***** LINE ***** ***** ***** ***** *****/
45 
47  : shape(cfg)
48  , x1_(cfg["x1"])
49  , y1_(cfg["y1"])
50  , x2_(cfg["x2"])
51  , y2_(cfg["y2"])
52  , color_(cfg["color"])
53  , thickness_(cfg["thickness"])
54 {
55  const std::string& debug = (cfg["debug"]);
56  if(!debug.empty()) {
57  DBG_GUI_P << "Line: found debug message '" << debug << "'.";
58  }
59 }
60 
62 {
63  /**
64  * @todo formulas are now recalculated every draw cycle which is a bit silly
65  * unless there has been a resize. So to optimize we should use an extra
66  * flag or do the calculation in a separate routine.
67  */
68 
69  const unsigned x1 = x1_(variables);
70  const unsigned y1 = y1_(variables);
71  const unsigned x2 = x2_(variables);
72  const unsigned y2 = y2_(variables);
73 
74  DBG_GUI_D << "Line: draw from " << x1 << ',' << y1 << " to " << x2 << ',' << y2 << ".";
75 
76  // @todo FIXME respect the thickness.
77 
78  draw::line(x1, y1, x2, y2, color_(variables));
79 }
80 
81 /***** ***** ***** ***** ***** Rectangle ***** ***** ***** ***** *****/
82 
84  : rect_bounded_shape(cfg)
85  , border_thickness_(cfg["border_thickness"])
86  , border_color_(cfg["border_color"], color_t::null_color())
87  , fill_color_(cfg["fill_color"], color_t::null_color())
88 {
89  // Check if a raw color string evaluates to a null color.
90  if(!border_color_.has_formula() && border_color_().null()) {
92  }
93 
94  const std::string& debug = (cfg["debug"]);
95  if(!debug.empty()) {
96  DBG_GUI_P << "Rectangle: found debug message '" << debug << "'.";
97  }
98 }
99 
101 {
102  const int x = x_(variables);
103  const int y = y_(variables);
104  const int w = w_(variables);
105  const int h = h_(variables);
106 
107  const color_t fill_color = fill_color_(variables);
108 
109  // Fill the background, if applicable
110  if(!fill_color.null()) {
111  DBG_GUI_D << "fill " << fill_color;
112  draw::set_color(fill_color);
113 
114  const SDL_Rect area {
115  x + border_thickness_,
116  y + border_thickness_,
117  w - (border_thickness_ * 2),
118  h - (border_thickness_ * 2)
119  };
120 
121  draw::fill(area);
122  }
123 
124  const color_t border_color = border_color_(variables);
125 
126  // Draw the border
127  draw::set_color(border_color);
128  DBG_GUI_D << "border thickness " << border_thickness_
129  << ", colour " << border_color;
130  for(int i = 0; i < border_thickness_; ++i) {
131  const SDL_Rect dimensions {
132  x + i,
133  y + i,
134  w - (i * 2),
135  h - (i * 2)
136  };
137 
138  draw::rect(dimensions);
139  }
140 }
141 
142 /***** ***** ***** ***** ***** Rounded Rectangle ***** ***** ***** ***** *****/
143 
145  : rect_bounded_shape(cfg)
146  , r_(cfg["corner_radius"])
147  , border_thickness_(cfg["border_thickness"])
148  , border_color_(cfg["border_color"], color_t::null_color())
149  , fill_color_(cfg["fill_color"], color_t::null_color())
150 {
151  // Check if a raw color string evaluates to a null color.
152  if(!border_color_.has_formula() && border_color_().null()) {
153  border_thickness_ = 0;
154  }
155 
156  const std::string& debug = (cfg["debug"]);
157  if(!debug.empty()) {
158  DBG_GUI_P << "Rounded Rectangle: found debug message '" << debug << "'.";
159  }
160 }
161 
163 {
164  const int x = x_(variables);
165  const int y = y_(variables);
166  const int w = w_(variables);
167  const int h = h_(variables);
168  const int r = r_(variables);
169 
170  DBG_GUI_D << "Rounded Rectangle: draw from " << x << ',' << y << " width " << w << " height " << h << ".";
171 
172  const color_t fill_color = fill_color_(variables);
173 
174  // Fill the background, if applicable
175  if(!fill_color.null() && w && h) {
176  draw::set_color(fill_color);
177 
178  draw::fill(rect{x + r, y + border_thickness_, w - r * 2, r - border_thickness_ + 1});
179  draw::fill(rect{x + border_thickness_, y + r + 1, w - border_thickness_ * 2, h - r * 2});
180  draw::fill(rect{x + r, y - r + h + 1, w - r * 2, r - border_thickness_});
181 
182  draw::disc(x + r, y + r, r, 0xc0);
183  draw::disc(x + w - r, y + r, r, 0x03);
184  draw::disc(x + r, y + h - r, r, 0x30);
185  draw::disc(x + w - r, y + h - r, r, 0x0c);
186  }
187 
188  const color_t border_color = border_color_(variables);
189 
190  // Draw the border
191  draw::set_color(border_color);
192 
193  for(int i = 0; i < border_thickness_; ++i) {
194  draw::line(x + r, y + i, x + w - r, y + i);
195  draw::line(x + r, y + h - i, x + w - r, y + h - i);
196 
197  draw::line(x + i, y + r, x + i, y + h - r);
198  draw::line(x + w - i, y + r, x + w - i, y + h - r);
199 
200  draw::circle(x + r, y + r, r - i, 0xc0);
201  draw::circle(x + w - r, y + r, r - i, 0x03);
202  draw::circle(x + r, y + h - r, r - i, 0x30);
203  draw::circle(x + w - r, y + h - r, r - i, 0x0c);
204  }
205 }
206 
207 /***** ***** ***** ***** ***** CIRCLE ***** ***** ***** ***** *****/
208 
210  : shape(cfg)
211  , x_(cfg["x"])
212  , y_(cfg["y"])
213  , radius_(cfg["radius"])
214  , border_color_(cfg["border_color"])
215  , fill_color_(cfg["fill_color"])
216  , border_thickness_(cfg["border_thickness"].to_int(1))
217 {
218  const std::string& debug = (cfg["debug"]);
219  if(!debug.empty()) {
220  DBG_GUI_P << "Circle: found debug message '" << debug << "'.";
221  }
222 }
223 
225 {
226  /**
227  * @todo formulas are now recalculated every draw cycle which is a bit
228  * silly unless there has been a resize. So to optimize we should use an
229  * extra flag or do the calculation in a separate routine.
230  */
231 
232  const int x = x_(variables);
233  const int y = y_(variables);
234  const unsigned radius = radius_(variables);
235 
236  DBG_GUI_D << "Circle: drawn at " << x << ',' << y << " radius " << radius << ".";
237 
238  const color_t fill_color = fill_color_(variables);
239  if(!fill_color.null() && radius) {
240  draw::disc(x, y, radius, fill_color);
241  }
242 
243  const color_t border_color = border_color_(variables);
244  for(unsigned int i = 0; i < border_thickness_; i++) {
245  draw::circle(x, y, radius - i, border_color);
246  }
247 }
248 
249 /***** ***** ***** ***** ***** IMAGE ***** ***** ***** ***** *****/
250 
252  : shape(cfg)
253  , x_(cfg["x"])
254  , y_(cfg["y"])
255  , w_(cfg["w"])
256  , h_(cfg["h"])
257  , image_name_(cfg["name"])
258  , resize_mode_(get_resize_mode(cfg["resize_mode"]))
259  , mirror_(cfg.get_old_attribute("mirror", "vertical_mirror", "image"))
260  , actions_formula_(cfg["actions"], &functions)
261 {
262  const std::string& debug = (cfg["debug"]);
263  if(!debug.empty()) {
264  DBG_GUI_P << "Image: found debug message '" << debug << "'.";
265  }
266 }
267 
268 void image_shape::dimension_validation(unsigned value, const std::string& name, const std::string& key)
269 {
270  const int as_int = static_cast<int>(value);
271 
272  VALIDATE_WITH_DEV_MESSAGE(as_int >= 0, _("Image doesn't fit on canvas."),
273  formatter() << "Image '" << name << "', " << key << " = " << as_int << "."
274  );
275 }
276 
278 {
279  DBG_GUI_D << "Image: draw.";
280 
281  /**
282  * @todo formulas are now recalculated every draw cycle which is a bit
283  * silly unless there has been a resize. So to optimize we should use an
284  * extra flag or do the calculation in a separate routine.
285  */
286  const std::string& name = image_name_(variables);
287 
288  if(name.empty()) {
289  DBG_GUI_D << "Image: formula returned no value, will not be drawn.";
290  return;
291  }
292 
293  // Texture filtering mode must be set on texture creation,
294  // so check whether we need smooth scaling or not here.
298  {
299  scale_quality = image::scale_quality::linear;
300  }
301  texture tex = image::get_texture(image::locator(name), scale_quality);
302 
303  if(!tex) {
304  ERR_GUI_D << "Image: '" << name << "' not found and won't be drawn.";
305  return;
306  }
307 
308  wfl::map_formula_callable local_variables(variables);
309  local_variables.add("image_original_width", wfl::variant(tex.w()));
310  local_variables.add("image_original_height", wfl::variant(tex.h()));
311 
312  int w = w_(local_variables);
313  dimension_validation(w, name, "w");
314 
315  int h = h_(local_variables);
316  dimension_validation(h, name, "h");
317 
318  local_variables.add("image_width", wfl::variant(w ? w : tex.w()));
319  local_variables.add("image_height", wfl::variant(h ? h : tex.h()));
320 
321  const int x = x_(local_variables);
322  const int y = y_(local_variables);
323 
324  // used in gui/dialogs/story_viewer.cpp
325  local_variables.add("clip_x", wfl::variant(x));
326  local_variables.add("clip_y", wfl::variant(y));
327 
328  // Execute the provided actions for this context.
329  wfl::variant(variables.fake_ptr()).execute_variant(actions_formula_.evaluate(local_variables));
330 
331  // If w or h is 0, assume it means the whole image.
332  if (!w) { w = tex.w(); }
333  if (!h) { h = tex.h(); }
334 
335  const SDL_Rect dst_rect { x, y, w, h };
336 
337  // What to do with the image depends on whether we need to tile it or not.
338  switch(resize_mode_) {
339  case resize_mode::tile:
340  draw::tiled(tex, dst_rect, false, mirror_(variables));
341  break;
343  draw::tiled(tex, dst_rect, true, mirror_(variables));
344  break;
346  draw::tiled_highres(tex, dst_rect, false, mirror_(variables));
347  break;
349  // Stretching is identical to scaling in terms of handling.
350  // Is this intended? That's what previous code was doing.
351  case resize_mode::scale:
352  // Filtering mode is set on texture creation above.
353  // Handling is otherwise identical to sharp scaling.
355  if(mirror_(variables)) {
356  draw::flipped(tex, dst_rect);
357  } else {
358  draw::blit(tex, dst_rect);
359  }
360  break;
361  default:
362  ERR_GUI_D << "Image: unrecognized resize mode.";
363  break;
364  }
365 }
366 
368 {
369  if(resize_mode == "tile") {
370  return resize_mode::tile;
371  } else if(resize_mode == "tile_center") {
373  } else if(resize_mode == "tile_highres") {
375  } else if(resize_mode == "stretch") {
376  return resize_mode::stretch;
377  } else if(resize_mode == "scale_sharp") {
379  } else if(resize_mode == "scale") {
380  return resize_mode::scale;
381  } else {
382  if(!resize_mode.empty()) {
383  ERR_GUI_E << "Invalid resize mode '" << resize_mode << "' falling back to 'scale'.";
384  }
385 
386  // Linear scaling just looks horrible as a default, especially on HDPI screens, and even
387  // for some non-pixel art (the logo, for example). Nearest-neighbor isn't perfect for those
388  // usecases, but it's definitely better, in my opinion.
389  //
390  // -- vultraz, 2022-08-20
392  }
393 }
394 
395 /***** ***** ***** ***** ***** TEXT ***** ***** ***** ***** *****/
396 
398  : rect_bounded_shape(cfg)
399  , font_family_(font::str_to_family_class(cfg["font_family"]))
400  , font_size_(cfg["font_size"])
401  , font_style_(decode_font_style(cfg["font_style"]))
402  , text_alignment_(cfg["text_alignment"])
403  , color_(cfg["color"])
404  , text_(cfg["text"])
405  , text_markup_(cfg["text_markup"], false)
406  , link_aware_(cfg["text_link_aware"], false)
407  , link_color_(cfg["text_link_color"], color_t::from_hex_string("ffff00"))
408  , maximum_width_(cfg["maximum_width"], -1)
409  , characters_per_line_(cfg["text_characters_per_line"])
410  , maximum_height_(cfg["maximum_height"], -1)
411 {
412  if(!font_size_.has_formula()) {
413  VALIDATE(font_size_(), _("Text has a font size of 0."));
414  }
415 
416  const std::string& debug = (cfg["debug"]);
417  if(!debug.empty()) {
418  DBG_GUI_P << "Text: found debug message '" << debug << "'.";
419  }
420 }
421 
423 {
424  assert(variables.has_key("text"));
425 
426  // We first need to determine the size of the text which need the rendered
427  // text. So resolve and render the text first and then start to resolve
428  // the other formulas.
429  const t_string text = text_(variables);
430 
431  if(text.empty()) {
432  DBG_GUI_D << "Text: no text to render, leave.";
433  return;
434  }
435 
436  font::pango_text& text_renderer = font::get_text_renderer();
437 
438  text_renderer
439  .set_link_aware(link_aware_(variables))
440  .set_link_color(link_color_(variables))
441  .set_text(text, text_markup_(variables));
442 
443  text_renderer.set_family_class(font_family_)
444  .set_font_size(font_size_(variables))
446  .set_alignment(text_alignment_(variables))
447  .set_foreground_color(color_(variables))
448  .set_maximum_width(maximum_width_(variables))
449  .set_maximum_height(maximum_height_(variables), true)
450  .set_ellipse_mode(variables.has_key("text_wrap_mode")
451  ? static_cast<PangoEllipsizeMode>(variables.query_value("text_wrap_mode").as_int())
452  : PANGO_ELLIPSIZE_END)
454 
455  wfl::map_formula_callable local_variables(variables);
456  const auto [tw, th] = text_renderer.get_size();
457 
458  // Translate text width and height back to draw-space, rounding up.
459  local_variables.add("text_width", wfl::variant(tw));
460  local_variables.add("text_height", wfl::variant(th));
461 
462  const int x = x_(local_variables);
463  const int y = y_(local_variables);
464  const int w = w_(local_variables);
465  const int h = h_(local_variables);
466  rect dst_rect{x, y, w, h};
467 
468  texture tex = text_renderer.render_and_get_texture();
469  if(!tex) {
470  DBG_GUI_D << "Text: Rendering '" << text << "' resulted in an empty canvas, leave.";
471  return;
472  }
473 
474  dst_rect.w = std::min(dst_rect.w, tex.w());
475  dst_rect.h = std::min(dst_rect.h, tex.h());
476 
477  draw::blit(tex, dst_rect);
478 }
479 
480 /***** ***** ***** ***** ***** CANVAS ***** ***** ***** ***** *****/
481 
483  : shapes_()
484  , blur_depth_(0)
485  , w_(0)
486  , h_(0)
487  , variables_()
488  , functions_()
489 {
490 }
491 
493  : shapes_(std::move(c.shapes_))
494  , blur_depth_(c.blur_depth_)
495  , w_(c.w_)
496  , h_(c.h_)
497  , variables_(c.variables_)
498  , functions_(c.functions_)
499 {
500 }
501 
503 {
504  // This early-return has to come before the `validate(rect.w <= w_)` check, as during the boost_unit_tests execution
505  // the debug_clock widget will have no shapes, 0x0 size, yet be given a larger rect to draw.
506  if(shapes_.empty()) {
507  DBG_GUI_D << "Canvas: empty (no shapes to draw).";
508  return;
509  }
510 
511  // Note: this doesn't update if whatever is underneath changes.
512  if(blur_depth_ && !blur_texture_) {
513  // Cache a blurred image of whatever is underneath.
514  SDL_Rect rect = draw::get_viewport();
516  s = blur_surface(s, blur_depth_);
517  blur_texture_ = texture(s);
518  }
519 
520  // Draw blurred background.
521  // TODO: hwaccel - this should be able to be removed at some point with shaders
522  if(blur_depth_ && blur_texture_) {
524  }
525 
526  // Draw items
527  for(auto& shape : shapes_) {
528  const lg::scope_logger inner_scope_logging_object__{log_gui_draw, "Canvas: draw shape."};
530  }
531 }
532 
533 void canvas::parse_cfg(const config& cfg)
534 {
535  log_scope2(log_gui_parse, "Canvas: parsing config.");
536 
537  for(const auto shape : cfg.all_children_range())
538  {
539  const std::string& type = shape.key;
540  const config& data = shape.cfg;
541 
542  DBG_GUI_P << "Canvas: found shape of the type " << type << ".";
543 
544  if(type == "line") {
545  shapes_.emplace_back(std::make_unique<line_shape>(data));
546  } else if(type == "rectangle") {
547  shapes_.emplace_back(std::make_unique<rectangle_shape>(data));
548  } else if(type == "round_rectangle") {
549  shapes_.emplace_back(std::make_unique<round_rectangle_shape>(data));
550  } else if(type == "circle") {
551  shapes_.emplace_back(std::make_unique<circle_shape>(data));
552  } else if(type == "image") {
553  shapes_.emplace_back(std::make_unique<image_shape>(data, functions_));
554  } else if(type == "text") {
555  shapes_.emplace_back(std::make_unique<text_shape>(data));
556  } else if(type == "pre_commit") {
557 
558  /* note this should get split if more preprocessing is used. */
559  for(const auto function : data.all_children_range())
560  {
561 
562  if(function.key == "blur") {
563  blur_depth_ = function.cfg["depth"];
564  } else {
565  ERR_GUI_P << "Canvas: found a pre commit function"
566  << " of an invalid type " << type << ".";
567  }
568  }
569 
570  } else {
571  ERR_GUI_P << "Canvas: found a shape of an invalid type " << type
572  << ".";
573 
574  assert(false);
575  }
576  }
577 }
578 
580 {
582  variables_.add("width", wfl::variant(w_));
583  variables_.add("height", wfl::variant(h_));
584 }
585 
587 {
588  w_ = size.x;
589  h_ = size.y;
591 }
592 
593 void canvas::clear_shapes(const bool force)
594 {
595  if(force) {
596  shapes_.clear();
597  } else {
598  auto conditional = [](const std::unique_ptr<shape>& s)->bool { return !s->immutable(); };
599 
600  auto iter = std::remove_if(shapes_.begin(), shapes_.end(), conditional);
601  shapes_.erase(iter, shapes_.end());
602  }
603 }
604 
605 /***** ***** ***** ***** ***** SHAPE ***** ***** ***** ***** *****/
606 
607 } // namespace gui2
Define the common log macros for the gui toolkit.
Drawing functions, for drawing things on the screen.
#define ERR_GUI_E
Definition: log.hpp:38
typed_formula< color_t > color_
The color of the line.
typed_formula< unsigned > y_
The center y coordinate of the circle.
#define DBG_GUI_P
Definition: log.hpp:66
int x2_
Definition: pump.cpp:135
resize_mode get_resize_mode(const std::string &resize_mode)
Converts a string to a resize mode.
Definition: canvas.cpp:367
void set_size(const point &size)
Definition: canvas.cpp:586
const_all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:978
int border_thickness_
Border thickness.
void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Set the drawing colour.
Definition: draw.cpp:91
int w() const
The draw-space width of the texture, in pixels.
Definition: texture.hpp:105
typed_formula< bool > mirror_
Mirror the image over the vertical axis.
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:40
int border_thickness_
Border thickness.
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
Definition: text.cpp:333
Collection of helper functions relating to Pango formatting.
round_rectangle_shape(const config &cfg)
Constructor.
Definition: canvas.cpp:144
Add a special kind of assert to validate whether the input from WML doesn&#39;t contain any problems that...
texture render_and_get_texture()
Returns the cached texture, or creates a new one otherwise.
Definition: text.cpp:116
void circle(int x, int y, int r, const color_t &c, uint8_t octants=0xff)
Draw a circle of the given colour.
Definition: draw.cpp:199
rectangle_shape(const config &cfg)
Constructor.
Definition: canvas.cpp:83
int as_int() const
Definition: variant.cpp:294
typed_formula< color_t > border_color_
The border color of the rounded rectangle.
int h() const
The draw-space height of the texture, in pixels.
Definition: texture.hpp:114
circle_shape(const config &cfg)
Constructor.
Definition: canvas.cpp:209
scale_quality
Definition: picture.hpp:239
typed_formula< unsigned > x2_
The end x coordinate of the line.
unsigned h_
The full height of the canvas.
Definition: canvas.hpp:163
Class holding common attribute names (for WML) and common implementation (in C++) for shapes placed w...
pango_text & set_link_aware(bool b)
Definition: text.cpp:505
std::string_view data
Definition: picture.cpp:206
typed_formula< int > maximum_height_
The maximum height for the text.
#define h
typed_formula< unsigned > y2_
The end y coordinate of the line.
void update_size_variables()
Update WFL size variables.
Definition: canvas.cpp:579
typed_formula< color_t > fill_color_
The border color of the rounded rectangle.
typed_formula< int > y_
The y coordinate of the rectangle.
#define VALIDATE_WITH_DEV_MESSAGE(cond, message, dev_message)
pango_text & set_font_style(const FONT_STYLE font_style)
Definition: text.cpp:391
point get_size()
Returns the size of the text, in drawing coordinates.
Definition: text.cpp:168
static std::string _(const char *str)
Definition: gettext.hpp:93
pango_text & get_text_renderer()
Returns a reference to a static pango_text object.
Definition: text.cpp:968
pango_text & set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
Definition: text.cpp:462
virtual void draw(wfl::map_formula_callable &variables)=0
Draws the canvas.
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:32
unsigned int border_thickness_
The border thickness of the circle.
void rect(const SDL_Rect &rect)
Draw a rectangle.
Definition: draw.cpp:141
#define ERR_GUI_P
Definition: log.hpp:69
void get_screen_size_variables(wfl::map_formula_callable &variable)
Gets a formula object with the screen size.
Definition: helper.cpp:96
wfl::map_formula_callable variables_
The variables of the canvas.
Definition: canvas.hpp:166
pango_text & set_alignment(const PangoAlignment alignment)
Definition: text.cpp:482
Generic file dialog.
void draw(wfl::map_formula_callable &variables) override
Draws the canvas.
Definition: canvas.cpp:61
int x1_
Definition: pump.cpp:135
int y2_
Definition: pump.cpp:135
#define DBG_GUI_D
Definition: log.hpp:29
Abstract base class for all other shapes.
Definition: canvas.hpp:52
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
static void dimension_validation(unsigned value, const std::string &name, const std::string &key)
Definition: canvas.cpp:268
lg::log_domain log_gui_parse("gui/parse")
Definition: log.hpp:65
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
shape(const config &cfg)
Definition: canvas.hpp:55
map_formula_callable & add(const std::string &key, const variant &value)
Definition: callable.hpp:253
std::ostringstream wrapper.
Definition: formatter.hpp:39
text_shape(const config &cfg)
Constructor.
Definition: canvas.cpp:397
void tiled_highres(const texture &tex, const SDL_Rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
Definition: draw.cpp:388
texture blur_texture_
Blurred background texture.
Definition: canvas.hpp:157
This file contains the canvas object which is the part where the widgets draw (temporally) images on...
typed_formula< unsigned > x_
The center x coordinate of the circle.
pango_text & set_characters_per_line(const unsigned characters_per_line)
Definition: text.cpp:426
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:58
wfl::formula actions_formula_
resize_mode resize_mode_
The resize mode for an image.
surface blur_surface(const surface &surf, int depth)
Cross-fades a surface.
Definition: utils.cpp:1204
wfl::action_function_symbol_table functions_
Action function definitions for the canvas.
Definition: canvas.hpp:169
#define log_scope2(domain, description)
Definition: log.hpp:238
typed_formula< bool > link_aware_
The link aware switch of the text.
typed_formula< bool > text_markup_
The text markup switch of the text.
font::family_class font_family_
The text font family.
typed_formula< color_t > fill_color_
The border color of the rectangle.
typed_formula< std::string > image_name_
Name of the image.
void draw(wfl::map_formula_callable &variables) override
Draws the canvas.
Definition: canvas.cpp:422
#define ERR_GUI_D
Definition: log.hpp:32
void draw(wfl::map_formula_callable &variables) override
Draws the canvas.
Definition: canvas.cpp:100
typed_formula< color_t > border_color_
The border color of the circle.
typed_formula< int > maximum_width_
The maximum width for the text.
typed_formula< int > x_
The x coordinate of the rectangle.
pango_text & set_family_class(font::family_class fclass)
Definition: text.cpp:369
Generic locator abstracting the location of an image.
Definition: picture.hpp:62
std::vector< std::unique_ptr< shape > > shapes_
Vector with the shapes to draw.
Definition: canvas.hpp:144
A simple canvas which can be drawn upon.
Definition: canvas.hpp:43
int y1_
Definition: pump.cpp:135
typed_formula< color_t > border_color_
The border color of the rectangle.
void tiled(const texture &tex, const SDL_Rect &dst, bool centered=false, bool mirrored=false)
Tile a texture to fill a region.
Definition: draw.cpp:360
typed_formula< int > w_
The width of the rectangle.
std::size_t i
Definition: function.cpp:967
typed_formula< unsigned > x_
The x coordinate of the image.
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:171
formula_callable_ptr fake_ptr()
Definition: callable.hpp:42
unsigned blur_depth_
The depth of the blur to use in the pre committing.
Definition: canvas.hpp:154
font::pango_text::FONT_STYLE font_style_
The style of the text.
void draw(wfl::map_formula_callable &variables) override
Draws the canvas.
Definition: canvas.cpp:277
void clear_shapes(const bool force)
Definition: canvas.cpp:593
static map_location::DIRECTION s
pango_text & set_font_size(unsigned font_size)
Definition: text.cpp:379
image_shape(const config &cfg, wfl::action_function_symbol_table &functions)
Constructor.
Definition: canvas.cpp:251
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:46
Holds a 2D point.
Definition: point.hpp:24
pango_text & set_link_color(const color_t &color)
Definition: text.cpp:514
line_shape(const config &cfg)
Constructor.
Definition: canvas.cpp:46
int w
#define debug(x)
lg::log_domain log_gui_draw("gui/draw")
Definition: log.hpp:28
typed_formula< unsigned > h_
The height of the image.
typed_formula< color_t > fill_color_
The fill color of the circle.
typed_formula< unsigned > y_
The y coordinate of the image.
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
Text class.
Definition: text.hpp:79
constexpr bool null() const
Definition: color.hpp:186
pango_text & set_maximum_width(int width)
Definition: text.cpp:410
resize_mode
Determines the way an image will be resized.
surface read_pixels_low_res(SDL_Rect *r)
The same as read_pixels, but returns a low-resolution surface suitable for use with the old drawing s...
Definition: video.cpp:603
typed_formula< t_string > text_
The text to draw.
Contains the SDL_Rect helper code.
variant query_value(const std::string &key) const
Definition: callable.hpp:50
void draw()
Draw the canvas&#39; shapes onto the screen.
Definition: canvas.cpp:502
typed_formula< PangoAlignment > text_alignment_
The alignment of the text.
typed_formula< color_t > link_color_
The link color of the text.
void flipped(const texture &tex, const SDL_Rect &dst, bool flip_h=true, bool flip_v=false)
Draws a texture, or part of a texture, at the given location, also mirroring/flipping the texture hor...
Definition: draw.cpp:331
typed_formula< unsigned > font_size_
The font size of the text.
typed_formula< int > r_
The radius of the corners.
typed_formula< unsigned > x1_
The start x coordinate of the line.
family_class str_to_family_class(const std::string &str)
unsigned characters_per_line_
The number of characters per line.
typed_formula< int > h_
The height of the rectangle.
void disc(int x, int y, int r, const color_t &c, uint8_t octants=0xff)
Draw a solid disc of the given colour.
Definition: draw.cpp:241
void draw(wfl::map_formula_callable &variables) override
Draws the canvas.
Definition: canvas.cpp:162
void draw(wfl::map_formula_callable &variables) override
Draws the canvas.
Definition: canvas.cpp:224
pango_text & set_maximum_height(int height, bool multiline)
Definition: text.cpp:437
bool has_formula() const
Determine whether the class contains a formula.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
texture get_texture(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image texture suitable for hardware-accelerated rendering.
Definition: picture.cpp:1128
typed_formula< color_t > color_
The color of the text.
mock_char c
void parse_cfg(const config &cfg)
Parses a config object.
Definition: canvas.cpp:533
SDL_Rect get_viewport()
Get the current viewport.
Definition: draw.cpp:558
pango_text & set_foreground_color(const color_t &color)
Definition: text.cpp:401
font::pango_text::FONT_STYLE decode_font_style(const std::string &style)
Converts a font style string to a font style.
Definition: helper.cpp:34
std::size_t w_
bool has_key(const std::string &key) const
Definition: callable.hpp:82
typed_formula< unsigned > y1_
The start y coordinate of the line.
void fill(const SDL_Rect &rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Fill an area with the given colour.
Definition: draw.cpp:41
typed_formula< unsigned > radius_
The radius of the circle.
unsigned w_
The full width of the canvas.
Definition: canvas.hpp:160
typed_formula< unsigned > w_
The width of the image.