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