The Battle for Wesnoth  1.19.7+dev
draw.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2022 - 2024
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 #pragma once
16 
17 /** @file
18  * Drawing functions, for drawing things on the screen.
19  *
20  * This includes pixel drawing for lines, rectangles and circles;
21  * fill and clear routines; and commands to render SDL surfaces and
22  * textures, in full or in part.
23  *
24  * For the most part draw commands take coordinates in what is called
25  * "draw space", or "game-native coordinates". These are the coordinates
26  * that are used in WML, and can be thought of as pixels.
27  *
28  * High-DPI textures and fonts will automatically use their full
29  * resolution when possible, without any extra handling required.
30  */
31 
32 #include "sdl/rect.hpp"
33 #include "sdl/texture.hpp"
34 
35 #include <vector>
36 
37 #include <SDL2/SDL_render.h>
38 #include <array>
39 
40 struct color_t;
41 
42 namespace draw
43 {
44 
45 /**************************************/
46 /* basic drawing and pixel primatives */
47 /**************************************/
48 
49 /**
50  * Clear the current render target.
51  *
52  * Sets all pixel values in the current render target to (0, 0, 0, 0),
53  * that is both black and fully transparent.
54  *
55  * To clear to a fully opaque colour in stead, use fill().
56  */
57 void clear();
58 
59 /**
60  * Fill an area with the given colour.
61  *
62  * If the alpha component is not specified, it defaults to fully opaque.
63  * If not fully opaque, the fill colour will apply according to the current
64  * blend mode, by default SDL_BLENDMODE_BLEND.
65  *
66  * If a fill area is not specified, it will fill the entire render target.
67  *
68  * @param rect The area to fill, in drawing coordinates.
69  * @param r The red component of the fill colour, 0-255.
70  * @param g The green component of the fill colour, 0-255.
71  * @param b The blue component of the fill colour, 0-255.
72  * @param a The alpha component of the fill colour, 0-255.
73  */
74 void fill(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
75 void fill(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b);
76 void fill(const SDL_Rect& rect, const color_t& color);
77 void fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
78 void fill(uint8_t r, uint8_t g, uint8_t b);
79 void fill(const color_t& color);
80 
81 /**
82  * Fill an area.
83  *
84  * Uses the current drawing colour set by set_draw_color().
85  * Coordinates are given in draw space.
86  *
87  * If a fill area is not specified, it will fill the entire render target.
88  *
89  * @param rect The area to fill, in drawing coordinates.
90  */
91 void fill(const SDL_Rect& rect);
92 void fill();
93 
94 /**
95  * Set the drawing colour.
96  *
97  * This is the colour used by fill(), line(), points(), etc..
98  *
99  * If the alpha component is not specified, it defaults to fully opaque.
100  *
101  * @param r The red component of the drawing colour, 0-255.
102  * @param g The green component of the drawing colour, 0-255.
103  * @param b The blue component of the drawing colour, 0-255.
104  * @param a The alpha component of the drawing colour, 0-255.
105  */
106 void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
107 void set_color(uint8_t r, uint8_t g, uint8_t b);
108 void set_color(const color_t& c);
109 
110 /**
111  * Set the blend mode used for drawing operations such as fill() and line().
112  *
113  * This does not affect texture drawing operations such as blit(). For those,
114  * use texture::set_blend_mode() on the texture before blitting.
115  */
116 void set_blend_mode(SDL_BlendMode b);
117 
118 /**
119  * Draw a rectangle.
120  *
121  * Uses the current drawing colour set by set_color().
122  * Coordinates are given in draw space.
123  *
124  * @param rect The rectangle to draw, in drawing coordinates.
125  */
126 void rect(const SDL_Rect& rect);
127 
128 /**
129  * Draw a rectangle using the given colour.
130  *
131  * @param rect The rectangle to draw, in drawing coordinates.
132  * @param r The red component of the drawing colour, 0-255.
133  * @param g The green component of the drawing colour, 0-255.
134  * @param b The blue component of the drawing colour, 0-255.
135  * @param a The alpha component of the drawing colour, 0-255.
136  */
137 void rect(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
138 void rect(const SDL_Rect& rect, uint8_t r, uint8_t g, uint8_t b);
139 void rect(const SDL_Rect& rect, const color_t& color);
140 
141 /**
142  * Draw a line.
143  *
144  * Uses the current drawing colour set by set_color().
145  * Coordinates are given in draw space.
146  *
147  * @param from_x The X coordinate of the start point, in draw space.
148  * @param from_y The Y coordinate of the start point, in draw space.
149  * @param to_x The X coordinate of the end point, in draw space.
150  * @param to_y The Y coordinate of the end point, in draw space.
151  */
152 void line(int from_x, int from_y, int to_x, int to_y);
153 
154 /**
155  * Draw a line of the given colour.
156  *
157  * @param from_x The X coordinate of the start point, in draw space.
158  * @param from_y The Y coordinate of the start point, in draw space.
159  * @param to_x The X coordinate of the end point, in draw space.
160  * @param to_y The Y coordinate of the end point, in draw space.
161  * @param c The RGBA colour of the line.
162  */
163 void line(int from_x, int from_y, int to_x, int to_y, const color_t& c);
164 
165 /** Draw a set of points. */
166 void points(const std::vector<SDL_Point>& points);
167 
168 /** Draw a single point. */
169 void point(int x, int y);
170 
171 // TODO: enum for common octant choices - nice but not necessary
172 /**
173  * Draw a circle of the given colour.
174  *
175  * Only the outline of the circle is drawn. To draw a filled circle,
176  * use draw::disc().
177  *
178  * The octants bitfield can be used to draw only certain octants
179  * of the circle, resulting in one or more arcs.
180  *
181  * If no colour is specified, the current drawing colour will be used.
182  *
183  * @param x The x coordinate of the center of the circle.
184  * @param y The y coordinate of the center of the circle.
185  * @param r The radius of the circle.
186  * @param c The colour of the circle.
187  * @param octants A bitfield indicating which octants to draw,
188  * starting at twelve o'clock and moving clockwise.
189  */
190 void circle(int x, int y, int r, const color_t& c, uint8_t octants = 0xff);
191 void circle(int x, int y, int r, uint8_t octants = 0xff);
192 
193 /**
194  * Draw a solid disc of the given colour.
195  *
196  * The octants bitfield can be used to draw only certain octants
197  * of the disc, resulting in one or more filled wedges.
198  *
199  * If no colour is specified, the current drawing colour will be used.
200  *
201  * @param x The x coordinate of the center of the circle.
202  * @param y The y coordinate of the center of the circle.
203  * @param r The radius of the circle.
204  * @param c The colour of the circle.
205  * @param octants A bitfield indicating which octants to draw,
206  * starting at twelve o'clock and moving clockwise.
207  */
208 void disc(int x, int y, int r, const color_t& c, uint8_t octants = 0xff);
209 void disc(int x, int y, int r, uint8_t octants = 0xff);
210 
211 
212 /*******************/
213 /* texture drawing */
214 /*******************/
215 
216 
217 /**
218  * Draws a texture, or part of a texture, at the given location.
219  *
220  * The portion of the texture to be drawn will be scaled to fill
221  * the target rectangle.
222  *
223  * This version takes coordinates in game-native resolution,
224  * which may be lower than the final output resolution in high-dpi
225  * contexts or if pixel scaling is used. The texture will be copied
226  * in high-resolution if possible.
227  *
228  * @param tex The texture to be copied / drawn.
229  * @param dst The target location to copy the texture to,
230  * in low-resolution game-native drawing coordinates.
231  * If null, this fills the entire render target.
232  */
233 void blit(const texture& tex, const SDL_Rect& dst);
234 void blit(const texture& tex);
235 
236 /**
237  * Draws a texture, or part of a texture, at the given location,
238  * also mirroring/flipping the texture horizontally and/or vertically.
239  *
240  * By default the texture will be flipped horizontally.
241  *
242  * @param tex The texture to be copied / drawn.
243  * @param dst The target location to copy the texture to,
244  * in low-resolution game-native drawing coordinates.
245  * If not given, the entire render target will be filled.
246  * @param flip_h Whether to flip/mirror the texture horizontally.
247  * @param flip_v Whether to flip/mirror the texture vertically.
248  */
249 void flipped(const texture& tex,
250  const SDL_Rect& dst,
251  bool flip_h = true,
252  bool flip_v = false
253 );
254 void flipped(const texture& tex, bool flip_h = true, bool flip_v = false);
255 
256 /**
257  * Tile a texture to fill a region.
258  *
259  * This function tiles the texture in draw-space.
260  *
261  * The texture may be aligned either with its center at the center
262  * of the region, or with its top-left corner at the top-left corner
263  * of the region.
264  *
265  * @param tex The texture to use to fill the region.
266  * @param dst The region to fill, in draw space.
267  * @param centered If true the tiled texture will be centered.
268  * If false, it will align at the top-left.
269  * @param mirrored If true the texture will be mirrored in such a way that
270  * adjacent tiles always share a common edge. This can look
271  * better for images that are not perfect tiles.
272  */
273 void tiled(const texture& tex,
274  const SDL_Rect& dst,
275  bool centered = false,
276  bool mirrored = false
277 );
278 
279 /** Tile a texture to fill a region.
280  *
281  * This function tiles the texture in output space. It is otherwise
282  * identical to draw::tiled().
283  */
284 void tiled_highres(const texture& tex,
285  const SDL_Rect& dst,
286  bool centered = false,
287  bool mirrored = false
288 );
289 
290 /**
291  * Draw a texture with smoothly varying colour and alpha modification,
292  * specified at the four corners of the drawing destination.
293  *
294  * The UV texture coordinates at each corner may also be specified.
295  * If unspecified, the full texture will be drawn.
296  *
297  * Colour modifiers multiply the output colour and alpha by their value
298  * after mapping to the range [0,1]. A value of 255 will have no effect.
299  *
300  * @param tex The texture to draw
301  * @param dst Where to draw the texture, in draw space
302  * @param cTL The colour modifier at the top-left corner
303  * @param cTR The colour modifier at the top-right corner
304  * @param cBL The colour modifier at the bottom-left corner
305  * @param cBR The colour modifier at the bottom-right corner
306  * @param uvTL The UV texture coordinate at the top-left corner
307  * @param uvTR The UV texture coordinate at the top-right corner
308  * @param uvBL The UV texture coordinate at the bottom-left corner
309  * @param uvBR The UV texture coordinate at the bottom-right corner
310  */
311 void smooth_shaded(const texture& tex, const SDL_Rect& dst,
312  const SDL_Color& cTL, const SDL_Color& cTR,
313  const SDL_Color& cBL, const SDL_Color& cBR,
314  const SDL_FPoint& uvTL, const SDL_FPoint& uvTR,
315  const SDL_FPoint& uvBL, const SDL_FPoint& uvBR
316 );
317 void smooth_shaded(const texture& tex, const SDL_Rect& dst,
318  const SDL_Color& cTL, const SDL_Color& cTR,
319  const SDL_Color& cBL, const SDL_Color& cBR
320 );
321 void smooth_shaded(const texture& tex,
322  const std::array<SDL_Vertex, 4>& verts
323 );
324 
325 /***************************/
326 /* RAII state manipulation */
327 /***************************/
328 
329 
330 /** A class to manage automatic restoration of the clipping region.
331  *
332  * This can be constructed on its own, or one of the utility functions
333  * override_clip() and reduce_clip() can be used. Constructing a clip_setter
334  * or using override_clip() will completely override the current clipping area.
335  * To intersect with the current clipping area in stead, use reduce_clip().
336  */
338 {
339 public:
340  explicit clip_setter(const SDL_Rect& clip);
341  ~clip_setter();
342 private:
343  SDL_Rect c_;
345 };
346 
347 /**
348  * Override the clipping area. All draw calls will be clipped to this region.
349  *
350  * The clipping area is specified in draw-space coordinates.
351  *
352  * The returned object will reset the clipping area when it is destroyed,
353  * so it should be kept in scope until drawing is complete.
354  *
355  * @param clip The clipping region in draw-space coordinates.
356  * @returns A clip_setter object. When this object is destroyed
357  * the clipping region will be restored to whatever
358  * it was before this call.
359  */
360 [[nodiscard]] clip_setter override_clip(const SDL_Rect& clip);
361 
362 /**
363  * Set the clipping area to the intersection of the current clipping
364  * area and the given rectangle.
365  *
366  * Otherwise acts as override_clip().
367  */
368 [[nodiscard]] clip_setter reduce_clip(const SDL_Rect& clip);
369 
370 /**
371  * Set the clipping area, without any provided way of setting it back.
372  *
373  * @param clip The clipping area, in draw-space coordinates.
374  */
375 void force_clip(const SDL_Rect& clip);
376 
377 /**
378  * Get the current clipping area, in draw coordinates.
379  *
380  * The clipping area is interpreted relative to the current viewport.
381  *
382  * If clipping is disabled, this will return the full drawing area.
383  */
384 ::rect get_clip();
385 
386 /** Whether clipping is enabled. */
387 bool clip_enabled();
388 
389 /** Disable clipping. To enable clipping, use set_clip() or force_clip(). */
390 void disable_clip();
391 
392 /**
393  * Whether the current clipping region will disallow drawing.
394  *
395  * This returns true for any clipping region with negative or zero width
396  * or height.
397  */
398 bool null_clip();
399 
400 
401 /** A class to manage automatic restoration of the viewport region.
402  *
403  * This will also translate the current clipping region into the space
404  * of the viewport, if a clipping region is set.
405  *
406  * This can be constructed on its own, or the draw::set_viewport()
407  * utility function can be used.
408  */
410 {
411 public:
412  explicit viewport_setter(const SDL_Rect& viewport);
414 private:
415  SDL_Rect v_;
416  SDL_Rect c_;
418 };
419 
420 /**
421  * Set the viewport. Drawing operations will have their coordinates
422  * adjusted to the viewport.
423  *
424  * The top-left corner of the viewport will be interpreted as (0,0) in
425  * draw space coordinates while the returned object is in scope.
426  *
427  * The new viewport is specified in absolute coordinates, relative to the
428  * full drawing surface.
429  *
430  * The returned object will reset the viewport when it is destroyed, so
431  * it should be kept in scope until viewport-relative drawing is complete.
432  *
433  * @param viewport The new viewport region, relative to the current
434  * viewport.
435  * @returns A viewport_setter object. When this object is
436  * destroyed the viewport will be restored to whatever
437  * it was before this call.
438  */
439 [[nodiscard]] viewport_setter set_viewport(const SDL_Rect& viewport);
440 
441 /**
442  * Set the viewport, without any provided way of setting it back.
443  *
444  * The new viewport is specified in absolute coordinates, relative to the
445  * full drawing surface.
446  *
447  * @param viewport The viewport, in absolute draw-space coordinates.
448  * If null, the viewport is reset to the full draw area.
449  */
450 void force_viewport(const SDL_Rect& viewport);
451 
452 /**
453  * Get the current viewport.
454  *
455  * @returns The current viewport, in the coordinate space of
456  * the original drawing surface
457  */
458 SDL_Rect get_viewport();
459 
460 
461 /**
462  * A class to manage automatic restoration of the render target.
463  *
464  * It will also cache and restore the current viewport.
465  *
466  * This can be constructed on its own, or the draw::set_render_target()
467  * utility function can be used.
468  */
470 {
471 public:
472  explicit render_target_setter(const texture& t);
474 
475 private:
479 };
480 
481 /**
482  * Set the given texture as the active render target.
483  *
484  * The current viewport will also be cached and restored along with the
485  * render target.
486  *
487  * All draw calls will draw to this texture until the returned object
488  * goes out of scope. Do not retain the render_target_setter longer
489  * than necessary.
490  *
491  * The provided texture must have been created with the
492  * SDL_TEXTUREACCESS_TARGET access mode.
493  *
494  * @param t The new render target. This must be a texture created
495  * with SDL_TEXTUREACCESS_TARGET, or an empty texture.
496  * If empty, it will set the render target to Wesnoth's
497  * primary render buffer.
498  * @returns A render_target_setter object. When this object is
499  * destroyed the render target will be restored to
500  * whatever it was before this call.
501  */
502 [[nodiscard]] render_target_setter set_render_target(const texture& t);
503 
504 
505 } // namespace draw
double t
Definition: astarsearch.cpp:63
double g
Definition: astarsearch.cpp:63
A class to manage automatic restoration of the clipping region.
Definition: draw.hpp:338
SDL_Rect c_
Definition: draw.hpp:343
bool clip_enabled_
Definition: draw.hpp:344
clip_setter(const SDL_Rect &clip)
Definition: draw.cpp:482
A class to manage automatic restoration of the render target.
Definition: draw.hpp:470
render_target_setter(const texture &t)
Definition: draw.cpp:628
A class to manage automatic restoration of the viewport region.
Definition: draw.hpp:410
viewport_setter(const SDL_Rect &viewport)
Definition: draw.cpp:569
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
Definition: draw.hpp:43
viewport_setter set_viewport(const SDL_Rect &viewport)
Set the viewport.
Definition: draw.cpp:596
void force_viewport(const SDL_Rect &viewport)
Set the viewport, without any provided way of setting it back.
Definition: draw.cpp:601
render_target_setter set_render_target(const texture &t)
Set the given texture as the active render target.
Definition: draw.cpp:664
clip_setter override_clip(const SDL_Rect &clip)
Override the clipping area.
Definition: draw.cpp:497
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:208
void points(const std::vector< SDL_Point > &points)
Draw a set of points.
Definition: draw.cpp:196
void force_clip(const SDL_Rect &clip)
Set the clipping area, without any provided way of setting it back.
Definition: draw.cpp:510
SDL_Rect get_viewport()
Get the current viewport.
Definition: draw.cpp:612
bool null_clip()
Whether the current clipping region will disallow drawing.
Definition: draw.cpp:555
clip_setter reduce_clip(const SDL_Rect &clip)
Set the clipping area to the intersection of the current clipping area and the given rectangle.
Definition: draw.cpp:502
bool clip_enabled()
Whether clipping is enabled.
Definition: draw.cpp:538
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:369
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:250
void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Set the drawing colour.
Definition: draw.cpp:100
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:340
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:50
void point(int x, int y)
Draw a single point.
Definition: draw.cpp:202
void clear()
Clear the current render target.
Definition: draw.cpp:40
void set_blend_mode(SDL_BlendMode b)
Set the blend mode used for drawing operations such as fill() and line().
Definition: draw.cpp:118
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:310
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:397
::rect get_clip()
Get the current clipping area, in draw coordinates.
Definition: draw.cpp:522
void rect(const SDL_Rect &rect)
Draw a rectangle.
Definition: draw.cpp:150
void disable_clip()
Disable clipping.
Definition: draw.cpp:546
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:180
void smooth_shaded(const texture &tex, const SDL_Rect &dst, const SDL_Color &cTL, const SDL_Color &cTR, const SDL_Color &cBL, const SDL_Color &cBR, const SDL_FPoint &uvTL, const SDL_FPoint &uvTR, const SDL_FPoint &uvBL, const SDL_FPoint &uvBR)
Draw a texture with smoothly varying colour and alpha modification, specified at the four corners of ...
Definition: draw.cpp:431
Contains the SDL_Rect helper code.
rect dst
Location on the final composed sheet.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:47
mock_char c
#define b