20 #define GETTEXT_DOMAIN "wesnoth-lib" 45 static void set_renderer_color(SDL_Renderer* renderer,
color_t color)
47 SDL_SetRenderDrawColor(renderer, color.
r, color.
g, color.
b, color.
a);
66 static void draw_line(
surface& canvas,
67 SDL_Renderer* renderer,
74 unsigned w = canvas->w;
76 DBG_GUI_D <<
"Shape: draw line from " << x1 <<
',' << y1 <<
" to " << x2
77 <<
',' << y2 <<
" canvas width " << w <<
" canvas height " 78 << canvas->h <<
".\n";
80 assert(static_cast<int>(x1) < canvas->w);
81 assert(static_cast<int>(x2) < canvas->w);
82 assert(static_cast<int>(y1) < canvas->h);
83 assert(static_cast<int>(y2) < canvas->h);
85 set_renderer_color(renderer, color);
87 if(x1 == x2 && y1 == y2) {
89 SDL_RenderDrawPoint(renderer, x1, y1);
91 SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
109 template<
unsigned int octants = 0xff>
110 static void draw_circle(
surface& canvas,
111 SDL_Renderer* renderer,
117 unsigned w = canvas->w;
119 DBG_GUI_D <<
"Shape: draw circle at " << x_center <<
',' << y_center
120 <<
" with radius " << radius <<
" canvas width " << w
121 <<
" canvas height " << canvas->h <<
".\n";
123 if(octants & 0x0f) assert((x_center + radius) < canvas->w);
124 if(octants & 0xf0) assert((x_center - radius) >= 0);
125 if(octants & 0x3c) assert((y_center + radius) < canvas->h);
126 if(octants & 0xc3) assert((y_center - radius) >= 0);
128 set_renderer_color(renderer, color);
133 int d = -
static_cast<int>(radius);
137 std::vector<SDL_Point> points;
140 if(octants & 0x04) points.push_back({x_center + x, y_center + y});
141 if(octants & 0x02) points.push_back({x_center + x, y_center - y});
142 if(octants & 0x20) points.push_back({x_center - x, y_center + y});
143 if(octants & 0x40) points.push_back({x_center - x, y_center - y});
145 if(octants & 0x08) points.push_back({x_center + y, y_center + x});
146 if(octants & 0x01) points.push_back({x_center + y, y_center - x});
147 if(octants & 0x10) points.push_back({x_center - y, y_center + x});
148 if(octants & 0x80) points.push_back({x_center - y, y_center - x});
158 SDL_RenderDrawPoints(renderer, points.data(), points.size());
175 template<
unsigned int octants = 0xff>
176 static void fill_circle(
surface& canvas,
177 SDL_Renderer* renderer,
183 unsigned w = canvas->w;
185 DBG_GUI_D <<
"Shape: draw filled circle at " << x_center <<
',' << y_center
186 <<
" with radius " << radius <<
" canvas width " << w
187 <<
" canvas height " << canvas->h <<
".\n";
189 if(octants & 0x0f) assert((x_center + radius) < canvas->w);
190 if(octants & 0xf0) assert((x_center - radius) >= 0);
191 if(octants & 0x3c) assert((y_center + radius) < canvas->h);
192 if(octants & 0xc3) assert((y_center - radius) >= 0);
194 set_renderer_color(renderer, color);
196 int d = -
static_cast<int>(radius);
203 if(octants & 0x04) SDL_RenderDrawLine(renderer, x_center + x, y_center + y + 1, x_center + y + 1, y_center + y + 1);
204 if(octants & 0x02) SDL_RenderDrawLine(renderer, x_center + x, y_center - y, x_center + y + 1, y_center - y);
205 if(octants & 0x20) SDL_RenderDrawLine(renderer, x_center - x - 1, y_center + y + 1, x_center - y - 2, y_center + y + 1);
206 if(octants & 0x40) SDL_RenderDrawLine(renderer, x_center - x - 1, y_center - y, x_center - y - 2, y_center - y);
208 if(octants & 0x08) SDL_RenderDrawLine(renderer, x_center + y, y_center + x + 1, x_center + y, y_center + y + 1);
209 if(octants & 0x01) SDL_RenderDrawLine(renderer, x_center + y, y_center - x, x_center + y, y_center - y);
210 if(octants & 0x10) SDL_RenderDrawLine(renderer, x_center - y - 1, y_center + x + 1, x_center - y - 1, y_center + y + 1);
211 if(octants & 0x80) SDL_RenderDrawLine(renderer, x_center - y - 1, y_center - x, x_center - y - 1, y_center - y);
233 , color_(cfg[
"color"])
234 , thickness_(cfg[
"thickness"])
236 const std::string&
debug = (cfg[
"debug"]);
238 DBG_GUI_P <<
"Line: found debug message '" << debug <<
"'.\n";
243 SDL_Renderer* renderer,
252 const unsigned x1 =
x1_(variables);
253 const unsigned y1 =
y1_(variables);
254 const unsigned x2 =
x2_(variables);
255 const unsigned y2 =
y2_(variables);
257 DBG_GUI_D <<
"Line: draw from " << x1 <<
',' << y1 <<
" to " << x2 <<
',' 258 << y2 <<
" canvas size " << canvas->w <<
',' << canvas->h
261 VALIDATE(static_cast<int>(x1) < canvas->w
262 && static_cast<int>(x2) < canvas->w
263 && static_cast<int>(y1) < canvas->h
264 && static_cast<int>(y2) < canvas->h,
265 _(
"Line doesn't fit on canvas."));
272 draw_line(canvas, renderer,
color_(variables), x1, y1, x2, y2);
283 , border_thickness_(cfg[
"border_thickness"])
284 , border_color_(cfg[
"border_color"],
color_t::null_color())
285 , fill_color_(cfg[
"fill_color"],
color_t::null_color())
292 const std::string&
debug = (cfg[
"debug"]);
294 DBG_GUI_P <<
"Rectangle: found debug message '" << debug <<
"'.\n";
299 SDL_Renderer* renderer,
307 const int x =
x_(variables);
308 const int y =
y_(variables);
309 const int w =
w_(variables);
310 const int h =
h_(variables);
312 DBG_GUI_D <<
"Rectangle: draw from " << x <<
',' << y <<
" width " << w
313 <<
" height " << h <<
" canvas size " << canvas->w <<
',' 314 << canvas->h <<
".\n";
317 && x + w <= canvas->w
319 && y + h <= canvas->h,
_(
"Rectangle doesn't fit on canvas."));
326 if(!fill_color.
null() && w &&
h) {
327 set_renderer_color(renderer, fill_color);
332 w - (border_thickness_ * 2),
333 h - (border_thickness_ * 2)
336 SDL_RenderFillRect(renderer, &area);
341 SDL_Rect dimensions {
350 SDL_RenderDrawRect(renderer, &dimensions);
362 , r_(cfg[
"corner_radius"])
372 const std::string&
debug = (cfg[
"debug"]);
374 DBG_GUI_P <<
"Rounded Rectangle: found debug message '" << debug <<
"'.\n";
379 SDL_Renderer* renderer,
387 const int x =
x_(variables);
388 const int y =
y_(variables);
389 const int w =
w_(variables);
390 const int h =
h_(variables);
391 const int r =
r_(variables);
393 DBG_GUI_D <<
"Rounded Rectangle: draw from " << x <<
',' << y <<
" width " << w
394 <<
" height " << h <<
" canvas size " << canvas->w <<
',' 395 << canvas->h <<
".\n";
398 && x + w <= canvas->w
400 && y + h <= canvas->h,
_(
"Rounded Rectangle doesn't fit on canvas."));
407 if(!fill_color.
null() && w &&
h) {
408 set_renderer_color(renderer, fill_color);
409 static const int count = 3;
410 SDL_Rect area[count] {
413 {x + r, y - r + h + 1, w - r * 2, r - border_thickness_},
416 SDL_RenderFillRects(renderer, area, count);
418 fill_circle<0xc0>(canvas, renderer, fill_color, x + r, y + r, r);
419 fill_circle<0x03>(canvas, renderer, fill_color, x + w - r, y + r, r);
420 fill_circle<0x30>(canvas, renderer, fill_color, x + r, y + h - r, r);
421 fill_circle<0x0c>(canvas, renderer, fill_color, x + w - r, y + h - r, r);
428 set_renderer_color(renderer, border_color);
430 SDL_RenderDrawLine(renderer, x + r, y +
i, x + w - r, y +
i);
431 SDL_RenderDrawLine(renderer, x + r, y + h -
i, x + w - r, y + h -
i);
433 SDL_RenderDrawLine(renderer, x +
i, y + r, x +
i, y + h - r);
434 SDL_RenderDrawLine(renderer, x + w -
i, y + r, x + w -
i, y + h - r);
436 draw_circle<0xc0>(canvas, renderer, border_color, x + r, y + r, r -
i);
437 draw_circle<0x03>(canvas, renderer, border_color, x + w - r, y + r, r -
i);
438 draw_circle<0x30>(canvas, renderer, border_color, x + r, y + h - r, r -
i);
439 draw_circle<0x0c>(canvas, renderer, border_color, x + w - r, y + h - r, r -
i);
449 , radius_(cfg[
"radius"])
454 const std::string&
debug = (cfg[
"debug"]);
456 DBG_GUI_P <<
"Circle: found debug message '" << debug <<
"'.\n";
461 SDL_Renderer* renderer,
470 const unsigned x =
x_(variables);
471 const unsigned y =
y_(variables);
472 const unsigned radius =
radius_(variables);
474 DBG_GUI_D <<
"Circle: drawn at " << x <<
',' << y <<
" radius " << radius
475 <<
" canvas size " << canvas->w <<
',' << canvas->h <<
".\n";
478 static_cast<int>(x - radius) >= 0,
479 _(
"Circle doesn't fit on canvas."),
480 formatter() <<
"x = " << x <<
", radius = " << radius);
483 static_cast<int>(y - radius) >= 0,
484 _(
"Circle doesn't fit on canvas."),
485 formatter() <<
"y = " << y <<
", radius = " << radius);
488 static_cast<int>(x + radius) < canvas->w,
489 _(
"Circle doesn't fit on canvas."),
490 formatter() <<
"x = " << x <<
", radius = " << radius
491 <<
"', canvas width = " << canvas->w <<
".");
494 static_cast<int>(y + radius) < canvas->h,
495 _(
"Circle doesn't fit on canvas."),
496 formatter() <<
"y = " << y <<
", radius = " << radius
497 <<
"', canvas height = " << canvas->h <<
".");
503 if(!fill_color.
null() && radius) {
504 fill_circle(canvas, renderer, fill_color, x, y, radius);
509 draw_circle(canvas, renderer, border_color, x, y, radius -
i);
523 , image_name_(cfg[
"name"])
524 , resize_mode_(get_resize_mode(cfg[
"resize_mode"]))
525 , vertical_mirror_(cfg[
"vertical_mirror"])
526 , actions_formula_(cfg[
"actions"], &functions)
528 const std::string&
debug = (cfg[
"debug"]);
530 DBG_GUI_P <<
"Image: found debug message '" << debug <<
"'.\n";
536 const int as_int =
static_cast<int>(value);
539 formatter() <<
"Image '" << name <<
"', " << key <<
" = " << as_int <<
"." 557 DBG_GUI_D <<
"Image: formula returned no value, will not be drawn.\n";
568 ERR_GUI_D <<
"Image: '" << name <<
"' not found and won't be drawn." << std::endl;
580 unsigned w =
w_(local_variables);
583 unsigned h =
h_(local_variables);
589 const unsigned clip_x =
x_(local_variables);
592 const unsigned clip_y =
y_(local_variables);
607 if ((w == 0) && (h == 0)) {
613 <<
image_->h <<
" to a height of " << h <<
".\n";
620 <<
',' <<
image_->h <<
" to a width of " << w
635 <<
image_->h <<
" to " << w <<
',' << h <<
".\n";
640 <<
image_->h <<
" to " << w <<
',' << h <<
".\n";
645 ERR_GUI_D <<
"Image: failed to stretch image, " 646 "fall back to scaling.\n";
650 <<
image_->h <<
" to " << w <<
',' << h <<
".\n";
668 if(resize_mode ==
"tile") {
670 }
else if(resize_mode ==
"tile_center") {
672 }
else if(resize_mode ==
"stretch") {
675 if(!resize_mode.empty() && resize_mode !=
"scale") {
676 ERR_GUI_E <<
"Invalid resize mode '" << resize_mode
677 <<
"' falling back to 'scale'.\n";
692 , font_size_(cfg[
"font_size"])
694 , text_alignment_(cfg[
"text_alignment"])
695 , color_(cfg[
"color"])
697 , text_markup_(cfg[
"text_markup"], false)
698 , link_aware_(cfg[
"text_link_aware"], false)
699 , link_color_(cfg[
"text_link_color"],
color_t::from_hex_string(
"ffff00"))
700 , maximum_width_(cfg[
"maximum_width"], -1)
701 , characters_per_line_(cfg[
"text_characters_per_line"])
702 , maximum_height_(cfg[
"maximum_height"], -1)
708 const std::string&
debug = (cfg[
"debug"]);
710 DBG_GUI_P <<
"Text: found debug message '" << debug <<
"'.\n";
718 assert(variables.
has_key(
"text"));
726 DBG_GUI_D <<
"Text: no text to render, leave.\n";
745 ?
static_cast<PangoEllipsizeMode
>(variables.
query_value(
"text_wrap_mode").
as_int())
746 : PANGO_ELLIPSIZE_END)
752 <<
"' resulted in an empty canvas, leave.\n";
770 const unsigned x =
x_(local_variables);
771 const unsigned y =
y_(local_variables);
772 const unsigned w =
w_(local_variables);
773 const unsigned h =
h_(local_variables);
775 DBG_GUI_D <<
"Text: drawing text '" << text <<
"' drawn from " << x <<
',' 776 << y <<
" width " << w <<
" height " << h <<
" canvas size " 777 << canvas->w <<
',' << canvas->h <<
".\n";
779 VALIDATE(static_cast<int>(x) < canvas->w && static_cast<int>(y) < canvas->h,
780 _(
"Text doesn't start on canvas."));
783 if(surf->w > static_cast<int>(w)) {
784 WRN_GUI_D <<
"Text: text is too wide for the " 785 "canvas and will be clipped.\n";
788 if(surf->h > static_cast<int>(h)) {
789 WRN_GUI_D <<
"Text: text is too high for the " 790 "canvas and will be clipped.\n";
820 ,
renderer_(std::exchange(
c.renderer_,
nullptr))
837 DBG_GUI_D <<
"Canvas: nothing to draw.\n";
848 DBG_GUI_D <<
"Canvas: use cached canvas.\n";
851 DBG_GUI_D <<
"Canvas: create new empty canvas.\n";
860 SDL_SetRenderDrawBlendMode(
renderer_, SDL_BLENDMODE_BLEND);
870 std::copy(shapes_.begin(), shapes_.end(), std::back_inserter(
drawn_shapes_));
911 DBG_GUI_P <<
"Canvas: found shape of the type " << type <<
".\n";
914 shapes_.emplace_back(std::make_shared<line_shape>(data));
915 }
else if(type ==
"rectangle") {
916 shapes_.emplace_back(std::make_shared<rectangle_shape>(data));
917 }
else if(type ==
"round_rectangle") {
918 shapes_.emplace_back(std::make_shared<round_rectangle_shape>(data));
919 }
else if(type ==
"circle") {
920 shapes_.emplace_back(std::make_shared<circle_shape>(data));
921 }
else if(type ==
"image") {
923 }
else if(type ==
"text") {
924 shapes_.emplace_back(std::make_shared<text_shape>(data));
925 }
else if(type ==
"pre_commit") {
931 if(
function.key ==
"blur") {
934 ERR_GUI_P <<
"Canvas: found a pre commit function" 935 <<
" of an invalid type " << type <<
".\n";
940 ERR_GUI_P <<
"Canvas: found a shape of an invalid type " << type
954 auto conditional = [](
const shape_ptr s)->
bool {
return !
s->immutable(); };
956 auto iter = std::remove_if(
shapes_.begin(),
shapes_.end(), conditional);
Define the common log macros for the gui toolkit.
typed_formula< color_t > color_
The color of the line.
typed_formula< unsigned > y_
The center y coordinate of the circle.
surface scale_surface_legacy(const surface &surf, int w, int h)
Scale a surface using simple bilinear filtering (discarding rgb from source pixels with 0 alpha) ...
resize_mode get_resize_mode(const std::string &resize_mode)
Converts a string to a resize mode.
const_all_children_itors all_children_range() const
In-order iteration over all children.
int border_thickness_
Border thickness.
bool is_dirty_
The dirty state of the canvas.
typed_formula< int > w_
The width of the rectangle.
void draw(surface &canvas, SDL_Renderer *renderer, wfl::map_formula_callable &variables) override
Implement shape::draw().
int border_thickness_
Border thickness.
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
Note: Specific to sdl_ttf.
round_rectangle_shape(const config &cfg)
Constructor.
surface image_
The image is cached in this surface.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
std::vector< shape_ptr > drawn_shapes_
All shapes which have been already drawn.
void draw(surface &canvas, SDL_Renderer *renderer, wfl::map_formula_callable &variables) override
Implement shape::draw().
rectangle_shape(const config &cfg)
Constructor.
typed_formula< color_t > border_color_
The border color of the rounded rectangle.
circle_shape(const config &cfg)
Constructor.
typed_formula< unsigned > x2_
The end x coordinate of the line.
unsigned h_
Height of the canvas.
t_string get_image() const
Wrapper for label.
pango_text & set_link_aware(bool b)
typed_formula< int > maximum_height_
The maximum height for the text.
static CVideo & get_singleton()
typed_formula< unsigned > y2_
The end y coordinate of the line.
typed_formula< color_t > fill_color_
The border color of the rounded rectangle.
surface get_surface_portion(const surface &src, SDL_Rect &area)
Get a portion of the screen.
#define VALIDATE_WITH_DEV_MESSAGE(cond, message, dev_message)
pango_text & set_font_style(const FONT_STYLE font_style)
static std::string _(const char *str)
pango_text & get_text_renderer()
Returns a reference to a static pango_text object.
pango_text & set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
surface flip_surface(const surface &surf)
typed_formula< int > w_
The width of the rectangle.
unsigned int border_thickness_
The border thickness of the circle.
void get_screen_size_variables(wfl::map_formula_callable &variable)
Gets a formula object with the screen size.
wfl::map_formula_callable variables_
The variables of the canvas.
pango_text & set_alignment(const PangoAlignment alignment)
typed_formula< bool > vertical_mirror_
Mirror the image over the vertical axis.
void blit_surface(const surface &surf, const SDL_Rect *srcrect, surface &dst, const SDL_Rect *dstrect)
Replacement for sdl_blit.
typed_formula< unsigned > h_
The height of the text.
typed_formula< int > h_
The height of the rectangle.
Abstract base class for all other shapes.
void blit(surface &surf, SDL_Rect rect)
Blits the canvas unto another surface.
static void dimension_validation(unsigned value, const std::string &name, const std::string &key)
lg::log_domain log_gui_parse("gui/parse")
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
text_shape(const config &cfg)
Constructor.
pango_text & set_font_size(const unsigned font_size)
This file contains the canvas object which is the part where the widgets draw (temporally) images on...
typed_formula< unsigned > w_
The width of the text.
typed_formula< int > y_
The y coordinate of the rectangle.
typed_formula< unsigned > x_
The center x coordinate of the circle.
pango_text & set_characters_per_line(const unsigned characters_per_line)
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.
wfl::action_function_symbol_table functions_
Action function definitions for the canvas.
#define log_scope2(domain, description)
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.
typed_formula< color_t > border_color_
The border color of the circle.
typed_formula< int > y_
The y coordinate of the rectangle.
typed_formula< unsigned > x_
The x coordinate of the text.
typed_formula< int > maximum_width_
The maximum width for the text.
pango_text & set_family_class(font::family_class fclass)
Generic locator abstracting the location of an image.
A simple canvas which can be drawn upon.
typed_formula< color_t > border_color_
The border color of the rectangle.
typed_formula< int > h_
The height of the rectangle.
typed_formula< unsigned > y_
The y coordinate of the text.
typed_formula< unsigned > x_
The x coordinate of the image.
unsigned blur_depth_
The depth of the blur to use in the pre committing.
font::pango_text::FONT_STYLE font_style_
The style of the text.
surface stretch_surface_horizontal(const surface &surf, const unsigned w)
Stretches a surface in the horizontal direction.
void clear_shapes(const bool force)
void draw(surface &canvas, SDL_Renderer *renderer, wfl::map_formula_callable &variables) override
Implement shape::draw().
static map_location::DIRECTION s
image_shape(const config &cfg, wfl::action_function_symbol_table &functions)
Constructor.
Helper class for pinning SDL surfaces into memory.
pango_text & set_link_color(const color_t &color)
line_shape(const config &cfg)
Constructor.
lg::log_domain log_gui_draw("gui/draw")
typed_formula< unsigned > h_
The height of the image.
typed_formula< color_t > fill_color_
The fill color of the circle.
bool is_neutral() const
Check that the surface is neutral bpp 32.
typed_formula< unsigned > y_
The y coordinate of the image.
virtual void draw(surface &canvas, SDL_Renderer *renderer, wfl::map_formula_callable &variables)=0
Draws the canvas.
SDL_Rect create_rect(const int x, const int y, const int w, const int h)
Creates an SDL_Rect with the given dimensions.
pango_text & set_maximum_width(int width)
resize_mode
Determines the way an image will be resized.
std::vector< shape_ptr > shapes_
Vector with the shapes to draw.
void draw(const bool force=false)
Draws the canvas.
SDL_Rect src_clip_
Contains the size of the image.
typed_formula< t_string > text_
The text to draw.
Contains the SDL_Rect helper code.
typed_formula< PangoAlignment > text_alignment_
The alignment of the text.
surface tile_surface(const surface &surf, int w, int h, bool centered)
Tile a surface.
typed_formula< color_t > link_color_
The link color of the text.
typed_formula< unsigned > font_size_
The font size of the text.
std::shared_ptr< shape > shape_ptr
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)
surface stretch_surface_vertical(const surface &surf, const unsigned h)
Stretches a surface in the vertical direction.
unsigned characters_per_line_
The number of characters per line.
void draw(surface &canvas, SDL_Renderer *renderer, wfl::map_formula_callable &variables) override
Implement shape::draw().
surface & render()
Returns the rendered text.
pango_text & set_maximum_height(int height, bool multiline)
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
void draw(surface &canvas, SDL_Renderer *renderer, wfl::map_formula_callable &variables) override
Implement shape::draw().
void draw(surface &canvas, SDL_Renderer *renderer, wfl::map_formula_callable &variables) override
Implement shape::draw().
A config object defines a single node in a WML file, with access to child nodes.
typed_formula< color_t > color_
The color of the text.
void parse_cfg(const config &cfg)
Parses a config object.
pango_text & set_foreground_color(const color_t &color)
surface canvas_
The surface we draw all items on.
font::pango_text::FONT_STYLE decode_font_style(const std::string &style)
Converts a font style string to a font style.
typed_formula< unsigned > y1_
The start y coordinate of the line.
typed_formula< int > x_
The x coordinate of the rectangle.
typed_formula< unsigned > radius_
The radius of the circle.
typed_formula< int > x_
The x coordinate of the rectangle.
unsigned w_
Width of the canvas.
typed_formula< unsigned > w_
The width of the image.