The Battle for Wesnoth  1.17.0-dev
canvas_private.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 - 2021
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 #include "gui/core/canvas.hpp"
18 
19 namespace gui2 {
20 
21 /**
22  * @ingroup GUICanvasWML
23  *
24  * Definition of a line.
25  * When drawing a line it doesn't get blended on the surface but replaces the pixels instead.
26  * A blitting flag might be added later if needed.
27  *
28  * Keys:
29  * Key |Type |Default |Description
30  * -------------|----------------------------------------|---------|-----------
31  * x1 | @ref guivartype_f_unsigned "f_unsigned"|0 |The x coordinate of the startpoint.
32  * y1 | @ref guivartype_f_unsigned "f_unsigned"|0 |The y coordinate of the startpoint.
33  * x2 | @ref guivartype_f_unsigned "f_unsigned"|0 |The x coordinate of the endpoint.
34  * y2 | @ref guivartype_f_unsigned "f_unsigned"|0 |The y coordinate of the endpoint.
35  * color | @ref guivartype_color "color" |"" |The color of the line.
36  * thickness | @ref guivartype_unsigned "unsigned" |0 |The thickness of the line; if 0 nothing is drawn.
37  * debug | @ref guivartype_string "string" |"" |Debug message to show upon creation this message is not stored.
38  *
39  * Variables:
40  * Key |Type |Description
41  * -------------------|----------------------------------------|-----------
42  * width | @ref guivartype_unsigned "unsigned" |The width of the canvas.
43  * height | @ref guivartype_unsigned "unsigned" |The height of the canvas.
44  * text | @ref guivartype_t_string "t_string" |The text to render on the widget.
45  * text_maximum_width | @ref guivartype_unsigned "unsigned" |The maximum width available for the text on the widget.
46  * text_maximum_height| @ref guivartype_unsigned "unsigned" |The maximum height available for the text on the widget.
47  * text_wrap_mode | @ref guivartype_int "int" |When the text doesn't fit in the available width there are several ways to fix that. This variable holds the best method. (NOTE this is a 'hidden' variable meant to copy state from a widget to its canvas so there's no reason to use this variable and thus its values are not listed and might change without further notice.)
48  * text_alignment | @ref guivartype_h_align "h_align" |The way the text is aligned inside the canvas.
49  *
50  * The size variables are copied to the window and will be determined at runtime.
51  * This is needed since the main window can be resized and the dialog needs to resize accordingly.
52  * The following variables are available:
53  * Key |Type |Description
54  * ---------------|------------------------------------|-----------
55  * screen_width | @ref guivartype_unsigned "unsigned"|The usable width of the Wesnoth main window.
56  * screen_height | @ref guivartype_unsigned "unsigned"|The usable height of the Wesnoth main window.
57  * gamemapx_offset| @ref guivartype_unsigned "unsigned"|The distance between left edge of the screen and the game map.
58  * gamemap_width | @ref guivartype_unsigned "unsigned"|The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.
59  * gamemap_height | @ref guivartype_unsigned "unsigned"|The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.
60  * mouse_x | @ref guivartype_unsigned "unsigned"|The x coordinate of the mouse pointer.
61  * mouse_y | @ref guivartype_unsigned "unsigned"|The y coordinate of the mouse pointer.
62  * window_width | @ref guivartype_unsigned "unsigned"|The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '"(screen_width)"'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '"(window_width)"'.
63  * window_height | @ref guivartype_unsigned "unsigned"|The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '"(screen_height)"'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '"(window_height)"'.
64  *
65  * Note when drawing the valid coordinates are:
66  * * 0 -> width - 1
67  * * 0 -> height -1
68  *
69  * Drawing outside this area will result in unpredictable results including crashing. (That should be fixed, when encountered.)
70  */
71 class line_shape : public canvas::shape {
72 public:
73  /**
74  * Constructor.
75  *
76  * @param cfg The config object to define the line.
77  */
78  explicit line_shape(const config& cfg);
79 
80  void draw(surface& canvas,
81  SDL_Renderer* renderer,
82  const SDL_Rect& viewport,
83  wfl::map_formula_callable& variables) override;
84 
85 private:
86  typed_formula<unsigned> x1_, /**< The start x coordinate of the line. */
87  y1_, /**< The start y coordinate of the line. */
88  x2_, /**< The end x coordinate of the line. */
89  y2_; /**< The end y coordinate of the line. */
90 
91  /** The color of the line. */
93 
94  /**
95  * The thickness of the line.
96  *
97  * if the value is odd the x and y are the middle of the line.
98  * if the value is even the x and y are the middle of a line
99  * with width - 1. (0 is special case, does nothing.)
100  */
101  unsigned thickness_;
102 };
103 
104 /**
105  * @ingroup GUICanvasWML
106  *
107  * Class holding common attribute names (for WML) and common implementation (in C++) for shapes
108  * placed with the 4 attributes x, y, w and h.
109  *
110  * Keys:
111  * Key |Type |Default|Description
112  * -------------------|----------------------------------------|-------|-----------
113  * x | @ref guivartype_f_unsigned "f_unsigned"|0 |The x coordinate of the top left corner.
114  * y | @ref guivartype_f_unsigned "f_unsigned"|0 |The y coordinate of the top left corner.
115  * w | @ref guivartype_f_unsigned "f_unsigned"|0 |The width of the rectangle.
116  * h | @ref guivartype_f_unsigned "f_unsigned"|0 |The height of the rectangle.
117  */
119 protected:
120  /**
121  * Constructor.
122  *
123  * @param cfg The config object to define the rectangle.
124  */
125  explicit rect_bounded_shape(const config& cfg);
126 
127  /**
128  * Where to draw, calculated from the x,y,w,h formulas but with different reference points used
129  * as the origin of the co-ordinate system.
130  */
132  /**
133  * True if there was no intersection between dst_on_widget and the viewport. If true, the
134  * data in the SDL_Rects must be ignored.
135  */
136  bool empty;
137  /** In the co-ordinate system that the WML uses, and unaffected by the view_bounds */
138  SDL_Rect dst_on_widget;
139  /** Intersection of dst_on_widget with view_bounds, in the co-ordinate system that the WML uses. */
140  SDL_Rect clip_on_widget;
141  /**
142  * Intersection of view_bounds with the shape, in co-ordinates with the shape's top-left at
143  * (0,0). For a text_shape, this co-ordinate system corresponds to the co-ordinates of the
144  * Cairo surface that Pango draws on.
145  */
146  SDL_Rect clip_in_shape;
147  /**
148  * Translation of dst_on_widget to the viewport's co-ordinates. Here (0,0) corresponds to
149  * view_bounds's top-left. Will often have negative values for x and y, and widths or
150  * heights larger than the viewport's size.
151  */
153  /** Where to draw, in the co-ordinates of the viewport, and restricted to the view_bounds. */
154  SDL_Rect dst_in_viewport;
155  };
156 
157  calculated_rects calculate_rects(const SDL_Rect& view_bounds, wfl::map_formula_callable& variables) const;
158 
159 private:
160  typed_formula<int> x_; /**< The x coordinate of the rectangle. */
161  typed_formula<int> y_; /**< The y coordinate of the rectangle. */
162  typed_formula<int> w_; /**< The width of the rectangle. */
163  typed_formula<int> h_; /**< The height of the rectangle. */
164 };
165 
166 /**
167  * @ingroup GUICanvasWML
168  *
169  * Definition of a rectangle.
170  * When drawing a rectangle it doesn't get blended on the surface but replaces the pixels instead.
171  * A blitting flag might be added later if needed.
172  *
173  * Keys:
174  * Key |Type |Default|Description
175  * -------------------|----------------------------------------|-------|-----------
176  * border_thickness | @ref guivartype_unsigned "unsigned" |0 |The thickness of the border if the thickness is zero it's not drawn.
177  * border_color | @ref guivartype_color "color" |"" |The color of the border if empty it's not drawn.
178  * fill_color | @ref guivartype_color "color" |"" |The color of the interior if omitted it's not drawn.
179  * debug | @ref guivartype_string "string" |"" |Debug message to show upon creation this message is not stored.
180  *
181  * Variables: see line_shape
182  */
184 public:
185  /**
186  * Constructor.
187  *
188  * @param cfg The config object to define the rectangle.
189  */
190  explicit rectangle_shape(const config& cfg);
191 
192  void draw(surface& canvas,
193  SDL_Renderer* renderer,
194  const SDL_Rect& viewport,
195  wfl::map_formula_callable& variables) override;
196 
197 private:
198  /**
199  * Border thickness.
200  *
201  * If 0 the fill color is used for the entire widget.
202  */
204 
205  /**
206  * The border color of the rectangle.
207  *
208  * If the color is fully transparent the border isn't drawn.
209  */
211 
212  /**
213  * The border color of the rectangle.
214  *
215  * If the color is fully transparent the rectangle won't be filled.
216  */
218 };
219 
220 /**
221  * @ingroup GUICanvasWML
222  *
223  * Definition of a rounded rectangle shape.
224  * When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead.
225  * A blitting flag might be added later if needed.
226  * Key |Type |Default |Description
227  * ----------------|----------------------------------------|---------|-----------
228  * corner_radius | @ref guivartype_f_unsigned "f_unsigned"|0 |The radius of the rectangle's corners.
229  * border_thickness| @ref guivartype_unsigned "unsigned" |0 |The thickness of the border; if the thickness is zero it's not drawn.
230  * border_color | @ref guivartype_color "color" |"" |The color of the border; if empty it's not drawn.
231  * fill_color | @ref guivartype_color "color" |"" |The color of the interior; if omitted it's not drawn.
232  * debug | @ref guivartype_string "string" |"" |Debug message to show upon creation; this message is not stored.
233  */
235 public:
236  /**
237  * Constructor.
238  *
239  * @param cfg The config object to define the round rectangle.
240  */
241  explicit round_rectangle_shape(const config& cfg);
242 
243  void draw(surface& canvas,
244  SDL_Renderer* renderer,
245  const SDL_Rect& viewport,
246  wfl::map_formula_callable& variables) override;
247 
248 private:
249  typed_formula<int> r_; /**< The radius of the corners. */
250 
251  /**
252  * Border thickness.
253  *
254  * If 0 the fill color is used for the entire widget.
255  */
257 
258  /**
259  * The border color of the rounded rectangle.
260  *
261  * If the color is fully transparent the border isn't drawn.
262  */
264 
265  /**
266  * The border color of the rounded rectangle.
267  *
268  * If the color is fully transparent the rounded rectangle won't be filled.
269  */
271 };
272 
273 /**
274  * @ingroup GUICanvasWML
275  *
276  * Definition of a circle.
277  * When drawing a circle it doesn't get blended on the surface but replaces the pixels instead.
278  * A blitting flag might be added later if needed.
279  *
280  * Keys:
281  * Key |Type |Default|Description
282  * -------------------|----------------------------------------|-------|-----------
283  * x | @ref guivartype_f_unsigned "f_unsigned"|0 |The x coordinate of the center.
284  * y | @ref guivartype_f_unsigned "f_unsigned"|0 |The y coordinate of the center.
285  * radius | @ref guivartype_f_unsigned "f_unsigned"|0 |The radius of the circle; if 0 nothing is drawn.
286  * color | @ref guivartype_color "color" |"" |The color of the circle.
287  * debug | @ref guivartype_string "string" |"" |Debug message to show upon creation this message is not stored.
288  *
289  * Variables: see line_shape
290  *
291  * Drawing outside the area will result in unpredictable results including crashing. (That should be fixed, when encountered.)
292  */
293 class circle_shape : public canvas::shape {
294 public:
295  /**
296  * Constructor.
297  *
298  * @param cfg The config object to define the circle.
299  */
300  explicit circle_shape(const config& cfg);
301 
302  void draw(surface& canvas,
303  SDL_Renderer* renderer,
304  const SDL_Rect& viewport,
305  wfl::map_formula_callable& variables) override;
306 
307 private:
308  typed_formula<unsigned> x_, /**< The center x coordinate of the circle. */
309  y_, /**< The center y coordinate of the circle. */
310  radius_; /**< The radius of the circle. */
311 
312  /** The border color of the circle. */
313  typed_formula<color_t> border_color_, fill_color_; /**< The fill color of the circle. */
314 
315  /** The border thickness of the circle. */
316  unsigned int border_thickness_;
317 };
318 
319 /**
320  * @ingroup GUICanvasWML
321  *
322  * Keys:
323  * Key |Type |Default|Description
324  * -------------------|------------------------------------------|-------|-----------
325  * x | @ref guivartype_f_unsigned "f_unsigned" |0 |The x coordinate of the top left corner.
326  * y | @ref guivartype_f_unsigned "f_unsigned" |0 |The y coordinate of the top left corner.
327  * w | @ref guivartype_f_unsigned "f_unsigned" |0 |The width of the image, if not zero the image will be scaled to the desired width.
328  * h | @ref guivartype_f_unsigned "f_unsigned" |0 |The height of the image, if not zero the image will be scaled to the desired height.
329  * resize_mode | @ref guivartype_resize_mode "resize_mode"|scale |Determines how an image is scaled to fit the wanted size.
330  * vertical_mirror | @ref guivartype_f_bool "f_bool" |false |Mirror the image over the vertical axis.
331  * name | @ref guivartype_string "string" |"" |The name of the image.
332  * debug | @ref guivartype_string "string" |"" |Debug message to show upon creation this message is not stored.
333  *
334  * Variables:
335  * Key |Type |Description
336  * ---------------------|--------------------------------------|-----------
337  * image_width | @ref guivartype_unsigned "unsigned" |The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)
338  * image_height | @ref guivartype_unsigned "unsigned" |The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)
339  * image_original_width | @ref guivartype_unsigned "unsigned" |The width of the image as stored on disk, can be used to set x or w (also y and h can be set).
340  * image_original_height| @ref guivartype_unsigned "unsigned" |The height of the image as stored on disk, can be used to set y or h (also x and y can be set).
341  *
342  * Also the general variables are available, see line_shape
343  */
344 class image_shape : public canvas::shape {
345 public:
346  /**
347  * Constructor.
348  *
349  * @param cfg The config object to define the image.
350  * @param functions WFL functions to execute.
351  */
352  image_shape(const config& cfg, wfl::action_function_symbol_table& functions);
353 
354  void draw(surface& canvas,
355  SDL_Renderer* renderer,
356  const SDL_Rect& viewport,
357  wfl::map_formula_callable& variables) override;
358 
359 private:
360  typed_formula<unsigned> x_, /**< The x coordinate of the image. */
361  y_, /**< The y coordinate of the image. */
362  w_, /**< The width of the image. */
363  h_; /**< The height of the image. */
364 
365  /** Contains the size of the image. */
366  SDL_Rect src_clip_;
367 
368  /** The image is cached in this surface. */
370 
371  /**
372  * Name of the image.
373  *
374  * This value is only used when the image name is a formula. If it isn't a
375  * formula the image will be loaded in the constructor. If it's a formula it
376  * will be loaded every draw cycles. This allows 'changing' images.
377  */
379 
380  /**
381  * Determines the way an image will be resized.
382  *
383  * If the image is smaller is needed it needs to resized, how is determined
384  * by the value of this enum.
385  */
386  enum resize_mode {
391  };
392 
393  /** Converts a string to a resize mode. */
394  resize_mode get_resize_mode(const std::string& resize_mode);
395 
396  /** The resize mode for an image. */
398 
399  /** Mirror the image over the vertical axis. */
401 
402  // TODO: use a typed_formula?
404 
405  static void dimension_validation(unsigned value, const std::string& name, const std::string& key);
406 };
407 
408 /**
409  * @ingroup GUICanvasWML
410  *
411  * Key |Type |Default |Description
412  * -------------------|------------------------------------------|---------|-----------
413  * font_family | @ref guivartype_font_style "font_style" |"sans" |The font family used for the text.
414  * font_size | @ref guivartype_f_unsigned "f_unsigned" |mandatory|The size of the text font.
415  * font_style | @ref guivartype_f_unsigned "f_unsigned" |"" |The style of the text.
416  * text_alignment | @ref guivartype_f_unsigned "f_unsigned" |"left" |The alignment of the text.
417  * color | @ref guivartype_color "color" |"" |The color of the text.
418  * text | @ref guivartype_f_tstring "f_tstring" |"" |The text to draw (translatable).
419  * text_markup | @ref guivartype_f_bool "f_bool" |false |Can the text have mark-up?
420  * text_link_aware | @ref guivartype_f_bool "f_bool" |false |Is the text link aware?
421  * text_link_color | @ref guivartype_string "string" |"#ffff00"|The color of links in the text.
422  * maximum_width | @ref guivartype_f_int "f_int" |-1 |The maximum width the text is allowed to be.
423  * maximum_height | @ref guivartype_f_int "f_int" |-1 |The maximum height the text is allowed to be.
424  * debug | @ref guivartype_string "string" |"" |Debug message to show upon creation this message is not stored.
425  *
426  * NOTE alignment could only be done with the formulas, but now with the text_alignment flag as well,
427  * older widgets might still use the formulas and not all widgets may expose the text alignment yet and when exposed not use it yet.
428  *
429  * Variables:
430  * Key |Type |Description
431  * -------------------|------------------------------------------|-----------
432  * text_width | @ref guivartype_unsigned "unsigned" |The width of the rendered text.
433  * text_height | @ref guivartype_unsigned "unsigned" |The height of the rendered text.
434  * Also the general variables are available, see line_shape
435  */
437 public:
438  /**
439  * Constructor.
440  *
441  * @param cfg The config object to define the text.
442  */
443  explicit text_shape(const config& cfg);
444 
445  void draw(surface& canvas,
446  SDL_Renderer* renderer,
447  const SDL_Rect& viewport,
448  wfl::map_formula_callable& variables) override;
449 
450 private:
451  /** The text font family. */
453 
454  /** The font size of the text. */
456 
457  /** The style of the text. */
459 
460  /** The alignment of the text. */
462 
463  /** The color of the text. */
465 
466  /** The text to draw. */
468 
469  /** The text markup switch of the text. */
471 
472  /** The link aware switch of the text. */
474 
475  /** The link color of the text. */
477 
478  /** The maximum width for the text. */
480 
481  /** The number of characters per line. */
483 
484  /** The maximum height for the text. */
486 };
487 
488 }
typed_formula< color_t > color_
The color of the line.
typed_formula< unsigned > y_
The center y coordinate of the circle.
int border_thickness_
Border thickness.
family_class
Font classes for get_font_families().
bool empty
True if there was no intersection between dst_on_widget and the viewport.
Definition of a rounded rectangle shape.
int border_thickness_
Border thickness.
Keys: Key Type DefaultDescription x f_unsigned 0 The x coordinate of the top left corner...
surface image_
The image is cached in this surface.
Where to draw, calculated from the x,y,w,h formulas but with different reference points used as the o...
typed_formula< color_t > border_color_
The border color of the rounded rectangle.
typed_formula< unsigned > x2_
The end x coordinate of the line.
void draw(surface &canvas, SDL_Renderer *renderer, const SDL_Rect &viewport, wfl::map_formula_callable &variables) override
Draws the canvas.
Definition: canvas.cpp:223
Class holding common attribute names (for WML) and common implementation (in C++) for shapes placed w...
typed_formula< int > maximum_height_
The maximum height for the text.
Key Type Default Description font_family font_style "sans" The font family used for the text...
typed_formula< unsigned > y2_
The end y coordinate of the line.
typed_formula< color_t > fill_color_
The border color of the rounded rectangle.
typed_formula< int > y_
The y coordinate of the rectangle.
unsigned int border_thickness_
The border thickness of the circle.
Definition of a rectangle.
Generic file dialog.
Definition: field-fwd.hpp:23
typed_formula< bool > vertical_mirror_
Mirror the image over the vertical axis.
Abstract base class for all other shapes.
Definition: canvas.hpp:51
Definition of a line.
This file contains the canvas object which is the part where the widgets draw (temporally) images on...
SDL_Rect dst_on_widget
In the co-ordinate system that the WML uses, and unaffected by the view_bounds.
wfl::formula actions_formula_
resize_mode resize_mode_
The resize mode for an image.
SDL_Rect clip_in_shape
Intersection of view_bounds with the shape, in co-ordinates with the shape&#39;s top-left at (0...
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.
SDL_Rect dst_in_viewport
Where to draw, in the co-ordinates of the viewport, and restricted to the view_bounds.
typed_formula< int > maximum_width_
The maximum width for the text.
typed_formula< int > x_
The x coordinate of the rectangle.
A simple canvas which can be drawn upon.
Definition: canvas.hpp:42
typed_formula< color_t > border_color_
The border color of the rectangle.
A viewport is an special widget used to view only a part of the widget it &#39;holds&#39;.
Definition: viewport.hpp:45
typed_formula< int > w_
The width of the rectangle.
font::pango_text::FONT_STYLE font_style_
The style of the text.
SDL_Rect clip_on_widget
Intersection of dst_on_widget with view_bounds, in the co-ordinate system that the WML uses...
Definition of a circle.
line_shape(const config &cfg)
Constructor.
Definition: canvas.cpp:208
typed_formula< color_t > fill_color_
The fill color of the circle.
typed_formula< unsigned > y_
The y coordinate of the image.
resize_mode
Determines the way an image will be resized.
SDL_Rect src_clip_
Contains the size of the image.
typed_formula< t_string > text_
The text to draw.
typed_formula< PangoAlignment > text_alignment_
The alignment of the text.
typed_formula< color_t > link_color_
The link color of the text.
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.
unsigned characters_per_line_
The number of characters per line.
typed_formula< int > h_
The height of the rectangle.
unsigned thickness_
The thickness of the line.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
typed_formula< color_t > color_
The color of the text.
SDL_Rect unclipped_around_viewport
Translation of dst_on_widget to the viewport&#39;s co-ordinates.
std::size_t w_
typed_formula< unsigned > y1_
The start y coordinate of the line.